prefer to use map-reduce to db.eval where possible

This commit is contained in:
Dan Crosta 2011-08-16 08:20:06 -04:00
parent 8bdb42827c
commit 5f05843403

View File

@ -1416,16 +1416,26 @@ class QuerySet(object):
:param field: the field to sum over; use dot-notation to refer to :param field: the field to sum over; use dot-notation to refer to
embedded document fields embedded document fields
""" """
sum_func = """ map_func = pymongo.code.Code("""
function(sumField) { function() {
var total = 0.0; emit(1, this[field] || 0);
db[collection].find(query).forEach(function(doc) {
total += (doc[sumField] || 0.0);
});
return total;
} }
""" """, scope={'field': field})
return self.exec_js(sum_func, field)
reduce_func = pymongo.code.Code("""
function(key, values) {
var sum = 0;
for (var i in values) {
sum += values[i];
}
return sum;
}
""")
for result in self.map_reduce(map_func, reduce_func, output='inline'):
return result.value
else:
return 0
def average(self, field): def average(self, field):
"""Average over the values of the specified field. """Average over the values of the specified field.
@ -1433,22 +1443,38 @@ class QuerySet(object):
:param field: the field to average over; use dot-notation to refer to :param field: the field to average over; use dot-notation to refer to
embedded document fields embedded document fields
""" """
average_func = """ map_func = pymongo.code.Code("""
function(averageField) { function() {
var total = 0.0; if (this.hasOwnProperty(field))
var num = 0; emit(1, {t: this[field] || 0, c: 1});
db[collection].find(query).forEach(function(doc) {
if (doc[averageField] !== undefined) {
total += doc[averageField];
num += 1;
}
});
return total / num;
} }
""" """, scope={'field': field})
return self.exec_js(average_func, field)
def item_frequencies(self, field, normalize=False, map_reduce=False): reduce_func = pymongo.code.Code("""
function(key, values) {
var out = {t: 0, c: 0};
for (var i in values) {
var value = values[i];
out.t += value.t;
out.c += value.c;
}
return out;
}
""")
finalize_func = pymongo.code.Code("""
function(key, value) {
return value.t / value.c;
}
""")
for result in self.map_reduce(map_func, reduce_func, finalize_f=finalize_func, output='inline'):
return result.value
else:
return 0
def item_frequencies(self, field, normalize=False, map_reduce=True):
"""Returns a dictionary of all items present in a field across """Returns a dictionary of all items present in a field across
the whole queried set of documents, and their corresponding frequency. the whole queried set of documents, and their corresponding frequency.
This is useful for generating tag clouds, or searching documents. This is useful for generating tag clouds, or searching documents.