Query an array of embedded documents in mongodb

1.3k views Asked by At

I'm having a little trouble writing a query that needs to compare a given value against a certain field in all embedded documents within an array. I will give an example to make the issue less abstract.

Let's say I want to use MongoDB to store the last queries that users on my network have entered into different online search engines. An entry in the collection would have a structure like this :

{
    '_id' : 'zinfandel', 
    'last_search' : [
        {
            'engine' : 'google.com',
            'query' : 'why is the sky blue' 
        },
        {
            'engine' : 'bing.com', 
            'query' : 'what is love'
        },
        {   'engine' : 'yahoo.com',
            'query' : 'how to tie a tie'
        }
    ]
}

Now let's say user username enters a new query into a certain engine. The code that stores this query in the DB needs to find out whether there already exists an entry for the engine that the user used. If yes, this entry is to be updated with the new query. If not, a new entry should be created. My idea is to do a $push only if there is no entry for the given engine and do a $set otherwise. For this purpose, I tried to write my push like this :

db.mycollection.update(
    { '_id' : username , search.$.engine : { '$ne' : engine } },
    { '$push' : { 'search.$.engine' : engine, 'search.$.query' : query } }
) 

However, this pushes a new embedded document even if there already was an entry for the given engine. The problem seems to be that the $ne operator doesn't work with arrays like I expect it to work. What I need is a way to make sure that not a single embedded document in the array has an "engine" entry that matches the specified engine.

Does anyone have an idea how to do that? Please tell me if I need to further clarify the question ...

1

There are 1 answers

1
Peter Kulik On BEST ANSWER

You can push the item into the array with the following command:

db.mycollection.update({
    _id: "zinfandel", 
    "last_search.engine": {
        $nin: ["notwellknownengine.com"]
    }
}, {
    $push: {
        "last_search": {
            "engine" : "notwellknownengine.com", 
            "query" : "stackoveflow.com"
        }
    }
});