Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb - matching a nested document with an unknown key

Tags:

mongodb

Within a collection I am storing some data, mapped against a mobile device UID which is generated elsewhere. For example:

{
    devices: {
        'b2e4fe52d4ab57fd55fa': { model: 'aPhone', number: 1111111 },
        'b2e4fe52d4ab57fd55fb': { model: 'bPhone', number: 2222222 },
        'b2e4fe52d4ab57fd55fc': { model: 'cPhone', number: 3333333 }
    }
}

Is there a way to retrieve the object representing one device without using the UID?

This would be easy for an array simply using an $elemMatch on either the model or number, but it seems it's use is limited only Arrays, is there an analogue operator for Documents?

like image 521
StickyCube Avatar asked Nov 28 '14 00:11

StickyCube


1 Answers

is there an analogue operator for Documents

No. There is no operator to match and project a single key value pair inside a document, without knowing the key.

You will have to write the code to do the post processing on each devices document, which may look like:

var devices = db.devices.findOne().devices; 
    var keys = Object.keys(devices);
    for(var i=0;i<keys.length;i++){
    var device = devices[keys[i]];
    if(device.model == 'aPhone' && device.number == 1111111)
    {
        print(keys[i]);
        // do the processing here
        break;
    }
}

In case you had an option to change your schema as below, which is much more flexible and looks logically correct too,

db.devices.insert({
    devices: [
        {"id":"b2e4fe52d4ab57fd55fa",  model: 'aPhone', number: 1111111 },
        {"id":"b2e4fe52d4ab57fd55fb",  model: 'bPhone', number: 2222222 },
        {"id":"b2e4fe52d4ab57fd55fc",  model: 'cPhone', number: 3333333 }
    ]
})

Then you have the luxury of achieving it with a simple find and project query.

db.devices.findOne({"devices.model":"aPhone",
                    "devices.number":1111111},
                   {"devices.$":1})
like image 137
BatScream Avatar answered Oct 09 '22 02:10

BatScream