MongoDB объединяет две коллекции с непревзойденными документами - PullRequest
1 голос
/ 30 апреля 2020

Я пытаюсь сравнить и найти разные документы из двух коллекций ниже, примеры, Версия Mongodb: 4.0 , ORM: пн goose

**col1: Has one new document**

    { "id" : 200001, "mobileNo" : #######001 }
    { "id" : 200002, "mobileNo" : #######002 } //mobileNo may not be unique.
    { "id" : 200003, "mobileNo" : #######002 }
    { "id" : 200004, "mobileNo" : #######004 }

**col2:**

    { "id" : 200001, "mobileNo" : #######001 }
    { "id" : 200002, "mobileNo" : #######002 }
    { "id" : 200003, "mobileNo" : #######003 }

Теперь я хочу вставить документ { "id" : 200004, "mobileNo" : #######004 } с col1 до col2 т.е. документы, которые не совпадают.

Это то, что я пробовал до сих пор:

const col1= await Col1.find({}, { mobileNo: 1,id: 1, _id: 0 })
 col1.forEach(async function (col1docs) {
    let col2doc = await Col2.find({ mobileNo: { $ne: col1docs.mobileNo}, 
    id:{$ne:col1docs.id} }, { mobileNo: 1, _id: 0, id: 1 })
     if (!(col2doc)) {
            Col2.insertMany(col1docs);

            }
        });

Я также пробовал использовать $ eq вместо $ ne, но я также не получаю непревзойденные документы, и они не вставляются. Какие-либо предложения??? Комбинация id + phoneNo уникальна

1 Ответ

1 голос
/ 30 апреля 2020

Я бы сказал, что вместо двух .find() вызовов плюс итерация и затем третий вызов для записи данных, попробуйте этот запрос:

db.col1.aggregate([
    {
      $lookup: {
        from: "col2",
        let: { id: "$id", mobileNo: "$mobileNo" },
        pipeline: [
          {
            $match: { $expr: { $and: [ { $eq: [ "$id", "$$id" ] }, { $gte: [ "$mobileNo", "$$mobileNo" ] } ] } }
          },
          { $project: { _id: 1 } } // limiting to `_id` as we don't need entire doc of `col2` - just need to see whether a ref exists or not
        ],
        as: "data"
      }
    },
    { $match: { data: [] } // Filtering leaves docs in `col1` which has no match in `col2`
    },
    { $project: { data: 0, _id: 0 } }
 ])

Тест: mongoplayground

Подробности: Из приведенного выше запроса вы получаете возможность указать условия в $ lookup , чтобы получить документы из col1, которые имеют ссылку в col2. Допустим, $lookup будет выполняться для каждого документа col1. Таким образом, уникальная комбинация id & mobileNo из текущего документа в col1 имеет совпадение в col2, тогда col2 do c '_id будет помещен в массив data, в конце то, что мы получим из col1, будет data: [], чтобы сказать, что не найдено подходящих документов для этих col1 do c. Теперь вы можете просто записать все возвращенные документы в col2, используя .insertMany(). На самом деле вы можете сделать все это, используя $ merge в версии MongoDB> 4.2 без необходимости второго вызова записи (.insertMany()).

Для вашего сценария в версии MongoDB> 4.2 что-то вроде этого объединит документы во вторую коллекцию:

{ $merge: 'col2' } // Has to be final stage in aggregation

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

...