Получите отличные встроенные документы - PullRequest
0 голосов
/ 25 мая 2020

У меня есть коллекция с такими элементами:

{
    "_id": {
        "$oid": "56d61033a378eccde8a8354f"
    },
    "id": "10021-2015-ENFO",
    "certificate_number": 9278806,
    "business_name": "ATLIXCO DELI GROCERY INC.",
    "date": "Feb 20 2015",
    "result": "No Violation Issued",
    "sector": "Cigarette Retail Dealer - 127",
    "address": {
        "city": "RIDGEWOOD",
        "zip": 11385,
        "street": "MENAHAN ST",
        "number": 1712
    }
}

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

Я думаю, что могу разбить задачу на следующие шаги:

  • получить все уникальные адреса и создать с ними отдельную коллекцию, назначив _id для каждой записи (как у меня read добавит его, если не указано)
  • объединить все address поля, чтобы вставить соответствующие _id для каждого встроенного документа в исходной коллекции

I выберите такие документы, как это:

db.ci.find({}, {"address":1, "_id":0});

, но я не могу выделить его с помощью функции Distinct или foreach. Я тоже пытаюсь использовать aggregate, но это не работает.

Может кто-нибудь дать мне несколько советов?

Я использую Ubuntu 20.04, mongodb 4.2.7 и код с расширение mongodb .

1 Ответ

1 голос
/ 26 мая 2020

Вы можете получить уникальное целое число, назначенное каждому в одной агрегации, используя $facet, чтобы сохранить исходные документы, используя $addToSet, чтобы получить список уникальных адресов, и $indexOfArray, чтобы присвоить значение каждому документу :

db.collection.aggregate([
  {$facet: {
      docs: [{$match: {}}],
      addresses: [
        {$group: {
            _id: null,
            address: {$addToSet: "$address"}
        }}
      ]
  }},
  {$unwind: "$docs"},
  {$unwind: "$addresses"},
  {$addFields: {
      "address.id": {
        $indexOfArray: [
          "$addresses.address",
          "$docs.address"
        ]
      }
  }},
  {$replaceRoot:{newRoot:"$docs"}},
  {$out:"new_collection"}
])

Игровая площадка

Если вы предпочитаете ObjectId, у вас есть правильная идея, одна агрегация для вывода уникальных адресов во временную коллекцию, чтобы каждый был автоматически -назначен _id, а затем вторая агрегация для внедрения этих значений _id в исходные документы. В этом примере я собрал _id исходного документа, чтобы упростить последующий поиск.

db.collection.aggregate([
  {$group:{
       _id:"$address",
       ids:{$push:"$_id"}
  }},
  {$project:{
       address:"$_id",
       ids:1,
       _id:0
  }},
  {$out: "temp_address_collection"}
])

Детская площадка

db.collection.aggregate([
  {$lookup:{
      from:"temp_address_collection",
      localField:"_id",
      foreignField:"ids",
      as: "matched"
  }},
  {$addFields:{matched:{$arrayElemAt:["$matched",0]}}},
  {$addFields:{"$address.id": "$matched._id"}},
  {$project:{matched:0}},
  {$out:"new_collection"}
])

Детская площадка

...