Как получить несколько результатов условной суммы для нескольких вложенных массивов с одним запросом в Mongodb?

чистое решение JavaScript будет выглядеть следующим образом:

function findNested(obj, key, memo) {
  var i,
      proto = Object.prototype,
      ts = proto.toString,
      hasOwn = proto.hasOwnProperty.bind(obj);

  if ('[object Array]' !== ts.call(memo)) memo = [];

  for (i in obj) {
    if (hasOwn(i)) {
      if (i === key) {
        memo.push(obj[i]);
      } else if ('[object Array]' === ts.call(obj[i]) || '[object Object]' === ts.call(obj[i])) {
        findNested(obj[i], key, memo);
      }
    }
  }

  return memo;
}

вот как вы будете использовать эту функцию:

findNested({'aa': 1, 'bb': 2, 'cc': {'d':{'x':9}}, dd:{'d':{'y':9}}}, 'd');

, и результатом будет:

[{x: 9}, {y: 9}]
0
задан harun 18 January 2019 в 07:35
поделиться

1 ответ

Итак, давайте начнем с упрощения набора данных, вставим список элементов в нашу коллекцию test:

var items = [{
  _id : 1,
  products: [
    {
      countryId: 1 
    },
    {
      countryId: 1
    },
    {
      countryId: 2
    },
    {
      countryId: 4
    },
  ],
  sellers: [
    {
      countryId: 2
    },
    {
      countryId: 2
    },
    {
      countryId: 1
    }
  ]  
},
{
  _id : 2,
  products: [
  {
    countryId: 2
  },
  {
    countryId: 2
  },
  {
    countryId: 3
  }
  ],
  sellers: [
  {
    countryId: 3
  },
  {
    countryId: 3
  },
  {
    countryId: 2
  },
  {
    countryId: 4
  }
  ]
}];

db.test.insertMany(items);

Затем мы можем использовать этап агрегации $facet для обработки нескольких конвейеры агрегации, так что давайте начнем с использования конвейера для productsOnCountryCount.

Для начала нам нужно развернуть все products в массиве, а затем сопоставить, затем на основе заданного идентификатора страны:

var countryId = 4;

db.test.aggregate([
  { "$unwind" : "$products" },
  { "$match" : { "products.countryId": countryId } }
]).pretty()
{
        "_id" : 1,
        "products" : {
                "countryId" : 4
        },
        "sellers" : [
                {
                        "countryId" : 2
                },
                {
                        "countryId" : 2
                },
                {
                        "countryId" : 1
                }
        ]
}

Теперь мы можем просто использовать счет в конце, чтобы получить количество всех продуктов:

db.test.aggregate([
  { "$unwind" : "$products" },
  { "$match" : { "products.countryId": countryId}},
  { "$count": "productsOnCountryCount" }])
{ "productsOnCountryCount" : 1 }

Это наш первый отсортированный конвейер, теперь давайте посмотрим на unavailableProductsCount:

Все, что нам нужно сделать, это сопоставить, где countryId находится в [ 1110], но не в массиве products, это может быть достигнуто простым этапом $match, тогда мы можем просто запустить подсчет сверху:

db.test.aggregate([
    { "$match" : {"sellers.countryId": countryId, "products.countryId" : { $ne: countryId } } },
    { "$count": "unavailableProductsCount" }])
{ "unavailableProductsCount" : 1 }

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

db.test.aggregate([
  { "$facet": {
    "productsOnCountryCount": [
      { "$unwind" : "$products" },
      { "$match" : { "products.countryId": countryId}},
      { "$count": "productsOnCountryCount" },
    ],
    "unavailableProductsCount": [
      { "$match" : {"sellers.countryId": countryId, "products.countryId" : { $ne: countryId } } },
      { "$count": "unavailableProductsCount" }
    ]
  }},
  { "$project": {
    "productsOnCountryCount": { "$arrayElemAt": ["$productsOnCountryCount.productsOnCountryCount", 0] },
    "unavailableProductsCount": { "$arrayElemAt": ["$unavailableProductsCount.unavailableProductsCount", 0] }
  }}
]);

{ "productsOnCountryCount" : 1, "unavailableProductsCount" : 1 }

Я считаю, что лучший способ использовать $facet - это просто разбить их на сначала трубы меньшего размера, а затем соедините их вместе в конце.

0
ответ дан Kevin Smith 18 January 2019 в 07:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: