pillarOfLight
pillarOfLight

Reputation: 8992

narrowing down mongo db query result

so I have this Mongo query:

{"r_rid" : "cr_448630" } 

which when I execute find() returns

{ 
    "_id" : { "$oid" : "soaifusladfjlasfjdkl2222"} , 
    "mg" : 1 , 
    "r_rid" : "cr_448630" , 
    "users" : { 
        "5" : { "duration" : 15305 , "last_ts" : 99999999} , 
        "33455" : { "duration" : 1563835 , "last_ts" : 1375826968} , 
        "33606" : { "duration" : 4230245 , "last_ts" : 1375914301} , 
        "33651" : { "duration" : 0 , "last_ts" : 1373305133}
    }
}

What if I just want to get the user with the index 33455

How do I go about modifying my mongo query

Sorry, mongo n00b here...

Upvotes: 0

Views: 149

Answers (2)

Derick
Derick

Reputation: 36784

I have few comments here, in general you can not just get a sub document out of a document as it's sole return value. The best you can get straight out of MongoDB as JohnnyHK writesis with:

db.test.find({"r_rid" : "cr_448630"}, {'users.33455': 1})

Returns:

{
  "_id": ObjectId("5202d6a2d3e4ab0f04cca6c2"),
  "users": {
    "33455": {
      "duration": 1563835,
      "last_ts": 1375826968
    }
  }
}

However, I have to make a few comments about your schema. As a guideline, you should not have a value as a key. The user ID "33455" is really not a key, as you can't predefine how many you will have and they are basically random names. It makes it really difficult to query with an index for just the user_id for example. You can now also use a numeric value, instead of a string as user ID, which again has better storage and indexing support. So my first suggestion would be to change that to:

{ 
    "_id" : { "$oid" : "soaifusladfjlasfjdkl2222"} , 
    "mg" : 1 , 
    "r_rid" : "cr_448630" , 
    "users" : [
        { "userid" : 5, "duration" : 15305 , "last_ts" : 99999999}, 
        { "userid": 33455, "duration" : 1563835 , "last_ts" : 1375826968}, 
        { "userid": 33606, "duration" : 4230245 , "last_ts" : 1375914301}, 
        { "userid": 33651, "duration" : 0 , "last_ts" : 1373305133}
    ]
}

However, that means that db.test.find({"r_rid" : "cr_448630"}, {'users.33455': 1}) no longer works.

So my second suggestion would be change from your document above into multiple documents, like this:

{ 
    "userid" : 5, "duration" : 15305 , "last_ts" : 99999999
    "mg" : 1 , "r_rid" : "cr_448630" , 
},
{ 
    "userid": 33455, "duration" : 1563835 , "last_ts" : 1375826968 
    "mg" : 1 , "r_rid" : "cr_448630" , 
},
{ 
    "userid": 33606, "duration" : 4230245 , "last_ts" : 1375914301
    "mg" : 1 , "r_rid" : "cr_448630" , 
},
{ 
    "userid": 33651, "duration" : 0 , "last_ts" : 1373305133
    "mg" : 1 , "r_rid" : "cr_448630" , 
}

As you can see, I've now duplicated mg and r_rid into each user document. This schema provides you with much easier querying, and also you can now make use of an index to query a r_rid with a user_id at the same time:

db.test.ensureIndex( { r_rid: 1, userid: 1 } );
db.test.find( { 'r_rid': "cr_448630", 'userid' : 33455 } );

Upvotes: 4

JohnnyHK
JohnnyHK

Reputation: 312095

You can specify which parts of the document you want included in the result via the second (projection) parameter to find:

db.test.find({"r_rid" : "cr_448630"}, {'users.33455': 1})

Returns:

{
  "_id": ObjectId("5202d6a2d3e4ab0f04cca6c2"),
  "users": {
    "33455": {
      "duration": 1563835,
      "last_ts": 1375826968
    }
  }
}

Upvotes: 0

Related Questions