var _ = require('underscore')._;

var metadataParams = ['url', 'permalink', 'siteMediaID', 
		'siteCode', 'icon', 'author', 
		'mediaName', 'duration', 'type'];
var statParams = ['plays', 'favorites'];
var allParams = metadataParams.concat(statParams);

var SearchResult = function(params) {
	_.each(metadataParams, function(key) {
		if (!_(params).has(key) || params[key] == null) {
			throw new Error('Search result data needs to have a parameter named "' + key + "'.");
		}
	});
	_.extend(this, _.pick(params, metadataParams));
	var stats = {querySimilarity: 1, playRelevance: 1, favoriteRelevance: 1, relevance: 0.5};
	stats = _.extend(stats, _.pick(params, statParams));
	stats.plays = parseInt(stats.plays) || 0;
	stats.favorites = parseInt(stats.favorites) || 0;
	stats.querySimilarity = 1;
	stats.playRelevance = 1;
	stats.favoriteRelevance = 1;
	this.stats = stats;
}

SearchResult.prototype = {
	calculateRelevance: function() {
    	var lambdaPlays = 0.70, 
    		lambdaFavorites = 0.30,
    		playRelevance = lambdaPlays * this.stats.playRelevance,
    		favRelevance = lambdaFavorites * this.stats.favoriteRelevance;
    		//console.log(playRelevance, favRelevance);
    	this.stats.relevance = (playRelevance + favRelevance) * this.stats.querySimilarity;	
	}
};

module.exports = {
	SearchResult: SearchResult
}
var _ = require('underscore')._;

function SearchResult(options) {
	_.extend(this, _.pick(options, 
		'url', 'permalink', 'siteMediaID', 
		'siteCode', 'icon', 'author', 
		'mediaName', 'duration', 'type'));
	var stats = {querySimilarity: 1, playRelevance: 1, favoriteRelevance: 1, relevance: 0.5};
	stats = _.extend(stats, _.pick(options, 'plays', 'favorites'));
	stats.plays = parseInt(stats.plays) || 0;
	stats.favorites = parseInt(stats.favorites) || 0;
	stats.querySimilarity = 1;
	stats.playRelevance = 1;
	stats.favoriteRelevance = 1;
	this.stats = stats;
}

SearchResult.prototype = {
	calculateRelevance: function() {
    	var lambdaPlays = 0.70, 
    		lambdaFavorites = 0.30,
    		playRelevance = lambdaPlays * this.stats.playRelevance,
    		favRelevance = lambdaFavorites * this.stats.favoriteRelevance;
    		//console.log(playRelevance, favRelevance);
    	this.stats.relevance = (playRelevance + favRelevance) * this.stats.querySimilarity;	
	}
};

module.exports = {
	SearchResult: SearchResult
}
--- 
+++ 
@@ -1,12 +1,20 @@
 var _ = require('underscore')._;
 
-function SearchResult(options) {
-	_.extend(this, _.pick(options, 
-		'url', 'permalink', 'siteMediaID', 
+var metadataParams = ['url', 'permalink', 'siteMediaID', 
 		'siteCode', 'icon', 'author', 
-		'mediaName', 'duration', 'type'));
+		'mediaName', 'duration', 'type'];
+var statParams = ['plays', 'favorites'];
+var allParams = metadataParams.concat(statParams);
+
+var SearchResult = function(params) {
+	_.each(metadataParams, function(key) {
+		if (!_(params).has(key) || params[key] == null) {
+			throw new Error('Search result data needs to have a parameter named "' + key + "'.");
+		}
+	});
+	_.extend(this, _.pick(params, metadataParams));
 	var stats = {querySimilarity: 1, playRelevance: 1, favoriteRelevance: 1, relevance: 0.5};
-	stats = _.extend(stats, _.pick(options, 'plays', 'favorites'));
+	stats = _.extend(stats, _.pick(params, statParams));
 	stats.plays = parseInt(stats.plays) || 0;
 	stats.favorites = parseInt(stats.favorites) || 0;
 	stats.querySimilarity = 1;
Use more thorough error checking in search results to ensure that all expected fields exist.
