Trouble querying ListField with mongoengine

fceruti picture fceruti · Nov 3, 2012 · Viewed 9.9k times · Source

I'm using mongoengine, and I've got the following situation,

My model:

class Item(Document):
   ...
   tags = ListField(StringField(max_length=30))

The query:

filters = {
    'tags__contains': query
}
tags_with_counter = Item.objects.filter(**filters).item_frequencies('tags')

This returns a list of tuples containing the name of the tag, and the frequency. What I want to do is get only tags that contain query and their respective frequency. How can I do that?

Answer

Gianfranco P. picture Gianfranco P. · Nov 6, 2012

Having this similar MongoEngine model and documents:

class Post(Document):
    title = StringField()
    tags = ListField(StringField())

post1 = Post(title='Fun with MongoEngine', tags=['mongodb', 'mongoengine']).save()
post2 = Post(title='Loving Mongo', tags=['mongodb']).save()

You'll store this:

{
  "tags": [ "mongodb", "mongoengine" ],
  "title": "Fun with MongoEngine"
}
{
  "tags": [ "mongodb" ],
  "title": "Loving Mongo"
}

In MongoDB, when you run find() it returns the documents that match your query.

So with the following query, you'll get an array of documents (Post objects) that have the tag mongodb in the array field tags. (actually, the 'tag' array is joined with an empty string and matched if contains value 'mongodb'):

Post.objects(tags__contains='mongodb')

(filter is just an alias of objects constructor)

So after you get the item frequencies, you need to get the ones you're interested.

tag_cloud = Post.objects(tags__contains='mongodb').item_frequencies('tags')

> print tag_cloud
{'mongodb': 2, 'mongoengine': 1}
> tag_cloud['mongodb']
2