В коллекции я храню некоторые данные, сопоставленные с UID мобильного устройства, который генерируется в другом месте. Например:

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

Есть ли способ получить объект, представляющий одно устройство, без использования UID?

Это было бы легко для массива, просто используя $elemMatch либо для модели, либо для номера, но кажется, что его использование ограничено только массивами, есть ли аналог оператора для документов?

9
StickyCube 28 Ноя 2014 в 03:36

2 ответа

есть ли аналог оператора для Документов

Нет. Нет оператора, который сопоставлял бы и проецировал одну пару ключ-значение внутри документа, не зная ключа.

Вам нужно будет написать код для постобработки документа каждого устройства, который может выглядеть так:

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;
    }
}

Если у вас была возможность изменить схему, как показано ниже, которая гораздо более гибкая и выглядит логически правильной,

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

Тогда вы можете позволить себе роскошь добиться этого с помощью простого запроса на поиск и проект.

db.devices.findOne({"devices.model":"aPhone",
                    "devices.number":1111111},
                   {"devices.$":1})
3
BatScream 28 Ноя 2014 в 05:18

Используйте $where, хотя это не рекомендуется, если у вас большие данные из-за производительности.

db.collection.find(
{ $where: function() {
  var input = { model: 'aPhone', number: 1111111 };  
  if(this.devices != undefined){  
  for(var key in this.devices){
    d = this.devices[key];
    if (d.model==input.model && d.number==input.number) return true;
    }
  }
  return false;
}})
-1
anhlc 28 Ноя 2014 в 05:08
Использование Where позволит нам просто написать условия для фильтрации документов, а не для редактирования информации.
 – 
BatScream
28 Ноя 2014 в 05:20