2011-12-30 1 views
0

Предположим, что у меня есть различные документы в разных коллекциях:Как включить различные каталоги в запрос в MongoDB?

На автомобили:

{ "_id": 32534534, "color": "red", ... } 

На дома:

{ "_id": 93867, "city": "Xanadu", ... } 

Как я могу получить соответствующий документ в документах ниже , в люди:

{ "name": "Alonso", "owns": [32534534], ... } 
{ "name": "Kublai Khan", "owns": [93867], ... } 

Могу ли я использовать что-то вроде кода ниже? (Обратите внимание, что я не уточняя каталог)

db.find({'_id': 93867}) 

Если нет, то вы могли бы предложить, чтобы достичь этого эфект?


Я только что нашел этот родственный вопрос: MongoDB: cross-collection queries

+0

В NoSQL предпочтительнее иметь встроенные документы по ссылке на другие коллекции. Пусть «автомобили» и «дома» будут встроены в коллекцию «людей» – Arseny

+0

@ Арсений: Как насчет случаев, когда (а) «автомобили» и «дома» могут принадлежать более чем одному человеку; и (б) «автомобили» и «дома» обычно (а также) запрашиваются отдельно, без какого-либо лица и без учета каких-либо отношений с его владельцем? Должен ли я представлять эти документы как сами по себе, так и встроенные в документы в коллекцию людей? –

ответ

2

Используя DBrefs, вы можете хранить ссылки на документы вне своей коллекции или даже в другой базе данных mongodb. Вам нужно будет получить ссылки в отдельных запросах, разные драйверы обрабатывают это по-другому, например, с помощью драйвера python вы можете auto dereference.

Пример ваших в Js оболочке может выглядеть следующим образом:

> red_car = {"color": "red", "model": "Ford Perfect"} 
{"color": "red", "model": "Ford Perfect"} 
> db.cars.save(red_car) 
> red_car 
{ 
    "color" : "red", 
    "model" : "Ford Perfect", 
    "_id" : ObjectId("4f041d96874e6f24e704f887") 
} 
> // Save as DBRef 
> alonso = {"name": "Alonso", "owns": [new DBRef('cars', red_car._id)]} 
{ 
    "name" : "Alonso", 
    "owns" : [ 
     { 
      "$ref" : "cars", 
      "$id" : ObjectId("4f041d96874e6f24e704f887") 
     } 
    ] 
} 
> db.people.save(alonso) 

Как вы можете видеть DBRefs является формальной спецификацией для ссылок объектов, которые всегда содержит ObjectId, но может также содержать информацию о базе данных и Коллекция. В приведенном выше примере вы можете увидеть, что он хранит коллекцию cars в поле $ref.Поиск тривиальна, как вы просто сделать запрос на dbref:

> dbref = new DBRef('cars', red_car._id) 
> red_car_owner = db.people.find({"owns": {$in: [dbref]}})[0] 
> red_car_owner 
{ 
    "_id" : ObjectId("4f0448e3a1c5cd097fc36a65"), 
    "name" : "Alonso", 
    "owns" : [ 
     { 
      "$ref" : "cars", 
      "$id" : ObjectId("4f0448d1a1c5cd097fc36a64") 
     } 
    ] 
} 

разыменования можно сделать с помощью команды fetch() в оболочке:

> red_car_owner.owns[0].fetch() 
{ 
    "_id" : ObjectId("4f0448d1a1c5cd097fc36a64"), 
    "color" : "red", 
    "model" : "Ford Perfect" 
} 

Однако в зависимости от вашего случая использования вы можете захотеть, чтобы оптимизировать это и написать код, который итерации над массивом owns, и делает как можно меньше find() запросов ...

+0

Спасибо, Росс. Использование DBrefs - лучшее решение. –

0

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

{ "_id": 32534534, "type": "car", "color": "red", ... } 
{ "_id": 93867, "type": "house", "city": "Xanadu", ... } 
0

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

{ "name": "Alonso", "owns": {ids:[32534534],type:'car'} ... } 
{ "name": "Kublai Khan", "owns":{ids:[93867],type:'house'} ... } 

так что теперь вы можете найти людей, кто владеет красный цвет автомобиля по

db.people.find({type:car,ids:32534534}) 

и зданий

db.people.find({type:house,ids:93867}) 
+0

Я на самом деле пытаюсь сделать обратное. У меня есть человек, и я хочу найти документ с идентификатором, указанным в «owns». –

Смежные вопросы