Reputation: 19817
Suppose each of my users can save many "smart searches":
user = {
'username':'johncit',
'smart_searches': [
{'name':'last 24 hrs','terms':{'modifiedby':datetime(2012,1,1),'title':'foobar'}},
{'name':'blabla','terms':{'title':'whatever','otherfield':500}}
]
}
Now say John hits his 'blabla' search. How do I get the terms? I can get all John's smart searches like this:
db.Users.find_one({
'username':'johncit','smart_searches':{'$elemMatch':{'Name':'blabla'}}})
But this returns the whole document, not just the terms for the 'blabla' search, which is what I really need. Do I then have to figure out the precise terms on the client-side? Or is this a case for putting 'smart_searches' in their own collection? Is there a better structure?
I would love to hear your thoughts.
Upvotes: 0
Views: 90
Reputation: 65877
Positional operator will do the trick
> db.Users.find({'username':'johncit','smart_searches':{'$elemMatch':{'name':'blabla'}}},{'smart_searches.$.terms':1}).pretty()
{
"_id" : ObjectId("5099ab303d550a068f16d5c5"),
"smart_searches" : [
{
"name" : "blabla",
"terms" : {
"title" : "whatever",
"otherfield" : 500
}
}
]
}
Update:
To update the terms with the positional operator, you can write
db.Users.update({'username':'johncit',
'smart_searches':{'$elemMatch':{'name':'blabla'}}},
{$set:{'smart_searches.$.terms':{title:'changed',otherfield:200}}},
false,true)
Upvotes: 2
Reputation: 312035
You want to use the $elemMatch
projection operator instead of the query operator.
db.Users.find_one(
{'username':'johncit', 'smart_searches.name':'blabla'},
{'username': 1, 'smart_searches': {'$elemMatch': {'name':'blabla'}}})
You don't need to use $elemMatch
in your query object because you're only matching one component: name
.
Upvotes: 0