QuerySet.item_frequencies works with non-list fields
This commit is contained in:
parent
4c68bc6c96
commit
4012722a8d
@ -916,20 +916,27 @@ class QuerySet(object):
|
|||||||
"""
|
"""
|
||||||
return self.exec_js(average_func, field)
|
return self.exec_js(average_func, field)
|
||||||
|
|
||||||
def item_frequencies(self, list_field, normalize=False):
|
def item_frequencies(self, field, normalize=False):
|
||||||
"""Returns a dictionary of all items present in a list 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.
|
||||||
|
|
||||||
:param list_field: the list field to use
|
If the field is a :class:`~mongoengine.ListField`, the items within
|
||||||
|
each list will be counted individually.
|
||||||
|
|
||||||
|
:param field: the field to use
|
||||||
:param normalize: normalize the results so they add to 1.0
|
:param normalize: normalize the results so they add to 1.0
|
||||||
"""
|
"""
|
||||||
freq_func = """
|
freq_func = """
|
||||||
function(listField) {
|
function(field) {
|
||||||
if (options.normalize) {
|
if (options.normalize) {
|
||||||
var total = 0.0;
|
var total = 0.0;
|
||||||
db[collection].find(query).forEach(function(doc) {
|
db[collection].find(query).forEach(function(doc) {
|
||||||
total += doc[listField].length;
|
if (doc[field].constructor == Array) {
|
||||||
|
total += doc[field].length;
|
||||||
|
} else {
|
||||||
|
total++;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,14 +946,19 @@ class QuerySet(object):
|
|||||||
inc /= total;
|
inc /= total;
|
||||||
}
|
}
|
||||||
db[collection].find(query).forEach(function(doc) {
|
db[collection].find(query).forEach(function(doc) {
|
||||||
doc[listField].forEach(function(item) {
|
if (doc[field].constructor == Array) {
|
||||||
|
doc[field].forEach(function(item) {
|
||||||
|
frequencies[item] = inc + (frequencies[item] || 0);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var item = doc[field];
|
||||||
frequencies[item] = inc + (frequencies[item] || 0);
|
frequencies[item] = inc + (frequencies[item] || 0);
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
return frequencies;
|
return frequencies;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
return self.exec_js(freq_func, list_field, normalize=normalize)
|
return self.exec_js(freq_func, field, normalize=normalize)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
limit = REPR_OUTPUT_SIZE + 1
|
limit = REPR_OUTPUT_SIZE + 1
|
||||||
|
@ -973,7 +973,7 @@ class QuerySetTest(unittest.TestCase):
|
|||||||
|
|
||||||
BlogPost(hits=1, tags=['music', 'film', 'actors']).save()
|
BlogPost(hits=1, tags=['music', 'film', 'actors']).save()
|
||||||
BlogPost(hits=2, tags=['music']).save()
|
BlogPost(hits=2, tags=['music']).save()
|
||||||
BlogPost(hits=3, tags=['music', 'actors']).save()
|
BlogPost(hits=2, tags=['music', 'actors']).save()
|
||||||
|
|
||||||
f = BlogPost.objects.item_frequencies('tags')
|
f = BlogPost.objects.item_frequencies('tags')
|
||||||
f = dict((key, int(val)) for key, val in f.items())
|
f = dict((key, int(val)) for key, val in f.items())
|
||||||
@ -995,6 +995,13 @@ class QuerySetTest(unittest.TestCase):
|
|||||||
self.assertAlmostEqual(f['actors'], 2.0/6.0)
|
self.assertAlmostEqual(f['actors'], 2.0/6.0)
|
||||||
self.assertAlmostEqual(f['film'], 1.0/6.0)
|
self.assertAlmostEqual(f['film'], 1.0/6.0)
|
||||||
|
|
||||||
|
# Check item_frequencies works for non-list fields
|
||||||
|
f = BlogPost.objects.item_frequencies('hits')
|
||||||
|
f = dict((key, int(val)) for key, val in f.items())
|
||||||
|
self.assertEqual(set(['1', '2']), set(f.keys()))
|
||||||
|
self.assertEqual(f['1'], 1)
|
||||||
|
self.assertEqual(f['2'], 2)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
def test_average(self):
|
def test_average(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user