Выберите поля для возврата из $ lookup - PullRequest
0 голосов
/ 28 мая 2018

У меня есть кусок кода, чтобы присоединить коллекцию A (образец) к коллекции B (локаторы).Я пробовал синтаксис $unwind, $group и $push, единственная проблема в том, что я не могу вернуть поле locator и record.


data = db.sample.aggregate([
{'$lookup': {
    'from': 'locators',
    'localField': "locator",
    'foreignField': "_id",
    'as': "metalocator"}}])

print(list(data))

, котороевозвращает

[
  {
    '_id': '599A65E1A80541BA',
    'locator': 'ABC',
    'record': 'Nicaragua',
    'metalocator': [{'_id': 'ABC', 'group': 'Location', 'section': 'Geo', 'cabinet': 'Country', 'record': 'string', 'status': 'integer'}]
  },
  { 
    '_id': '428E970995AE8C76',
    'locator': 'CDE',
    'record': 'Nigeria',
    'metalocator': [{'_id': 'CDE', 'group': 'Location', 'section': 'Geo', 'cabinet': 'Country', 'record': 'string', 'status': 'integer'}]
  }
]

попытка 1

data = db.sample.aggregate([
    {"$lookup": {"from": "locators",
                 "localField": "locator",
                 "foreignField": "_id",
                 "as": "metalocator"}},
    {"$unwind": '$metalocator'},
    {"$group": {"_id": "$_id",
                "metalocator": {"$push":  {
                    "section": "$metalocator.section",
                    "cabinet": "$metalocator.cabinet"}}}}
])
print(list(data))

Что возвращает:

[
  {
    '_id': '1835853D2982AAEF',
    'metalocator': [{'section': 'Geo', 'cabinet': 'Country'}]
  },
  {
    '_id': '428E970995AE8C76',
    'metalocator': [{'section': 'Geo', 'cabinet': 'Country'}]
  }
]

Ожидаемый результат должен быть:

[
  {
    '_id': '1835853D2982AAEF',
    'locator': 'ABC',
    'record': 'Nicaragua',
    'metalocator': [{'section': 'Geo', 'cabinet': 'Country'}]
  },
  {
    '_id': '428E970995AE8C76',
    'locator': 'CDE',
    'record': 'Nigeria',
    'metalocator': [{'section': 'Geo', 'cabinet': 'Country'}]
  }
]

1 Ответ

0 голосов
/ 28 мая 2018

Вы хотите $map:

db.sample.aggregate([
  {'$lookup': {
    'from': 'locators',
    'localField': "locator",
    'foreignField': "_id",
    'as': "metalocator"
  }},
  { '$addFields': {
    'metalocator': {
      '$map': {
        'input': '$metalocator',
        'in': {
          'section': '$$this.section',
          'cabinet': '$$this.cabinet'
        }
      }
    }
  }}
 ])

Это то, что вы используете, чтобы «переназначить» содержимое массива, что действительно является тем, о чем вы спрашиваете.Его использование во многом аналогично использованию оператора с таким же именем в python, как и во многих других языках.

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

db.sample.aggregate([
  {'$lookup': {
    'from': 'locators',
    'let': { 'locator': '$locator' },
    'pipeline': [
      { '$match': {
        '$expr': { '$eq': [ '$_id', '$$locator' ] }
      }},
      { '$project': { 'section': 1, 'cabinet': 1, '_id': 0 } }
    ],
    'as': "metalocator"
  }}
])

Это было бы на самом деле более эффективно, когда вы можете это сделать, поскольку данные просто даже не возвращаются в целевой массив, а выне нужно «повторно отображать» массив, чтобы отбросить другие поля.

Для записи то, что вы «пропустили», это оператор $first:

db.sample.aggregate([
  { "$lookup": {
    "from": "locators",
    "localField": "locator",
    "foreignField": "_id",
    "as": "metalocator"
  }},
  { "$unwind": '$metalocator'},
  { "$group": {
    "_id": "$_id",
    "locator": { "$first": "$locator" },
    "record": { "$first": "$record" },
    "metalocator": {
      "$push":  {
        "section": "$metalocator.section",
        "cabinet": "$metalocator.cabinet"
      }
    }
  }}
])

Но использование $unwind и $group здесь не требуется, так как другие методы, показанные выше, гораздо более эффективны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...