2016-10-28 2 views
2

Учитывая данные:MongoDB - простой суб пример запроса

> db.parameters.find({}) 
{ "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"), "name" : "Speed", "groups" : [ " 
123", "234" ] } 
> db.groups.find({}) 
{ "_id" : "123", "name" : "Group01" } 
{ "_id" : "234", "name" : "Group02" } 
{ "_id" : "567", "name" : "Group03" } 

Я хотел бы поставить параметр _id в сделать запрос возвращает все группы, которые находятся в пределах групп массива данного документа в параметров стол.

Прямое решение, кажется, делает несколько DB заезжают PyMongo:

  1. Получить параметр от параметров таблицы на основе прилагаемого _id
  2. Для каждого элемента групп массива выбрать документ из группы

Но у этого будет так много лишних накладных расходов. Я считаю, что в MongoDB должен быть лучший и быстрый способ (без запуска пользовательского JS в БД). Или мне нужно переструктурировать мои данные, немного изменив его (например, таблицу отношений), пренебрегая подходом на основе документов?

Опять же, пожалуйста, помогите мне найти решение, которое будет работать с интерфейсом PyMongo DB

ответ

5

Вы можете сделать это в рамках одного запроса с использованием рамок агрегации. В частности, вам нужно будет запустить конвейер агрегации, в котором используется оператор $lookup, чтобы сделать левое соединение из коллекции parameters коллекции groups.

Рассмотрим запустив следующую трубопровод:

db.parameters.aggregate([ 
    { "$unwind": "$groups" }, 
    { 
     "$lookup": { 
      "from": "groups", 
      "localField": "groups", 
      "foreignField": "_id", 
      "as": "grp" 
     } 
    }, 
    { "$unwind": "$grp" } 
]) 

Пример вывода

/* 1 */ 
{ 
    "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"), 
    "name" : "Speed", 
    "groups" : "123", 
    "grp" : { 
     "_id" : "123", 
     "name" : "Group01" 
    } 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("56cac0cd0b5a1ffab1bd6c12"), 
    "name" : "Speed", 
    "groups" : "234", 
    "grp" : { 
     "_id" : "234", 
     "name" : "Group02" 
    } 
} 

Если ваша версия MongoDB сервер не поддерживает оператор конвейера в $lookup, то вы бы необходимо выполнить два запроса следующим образом:

# get the group ids 
ids = db.parameters.find_one({ "_id": ObjectId("56cac0cd0b5a1ffab1bd6c12") })["groups"] 

# query the groups collection with the ids from previous query 
db.groups.find({ "_id": { "$in": ids } }) 

EDIT: соответствует имени поля в агрегации запрос на имя поля в наборе данных, например (в пределах вопроса)