В конвейере агрегации MongoDB, как спроектировать индексы встроенного массива, которые соответствуют? - PullRequest
1 голос
/ 08 июня 2019

В конвейере агрегации mongodb я хочу $project индексы встроенного массива (вложенного документа), который соответствует предыдущему этапу $match.

Скажем, у меня есть следующие документы.

{_id: '1', tags: ['aaa', 'bbb', 'ccc']},
{_id: '2', tags: ['baa', 'aaa', 'aaa']},
{_id: '3', tags: ['aac', 'cbb', 'aca']},

Теперь, если я сделаю запрос с {tags: 'aaa'}, я хочу вывести что-то похожее на

{_id: '1', tags: [0]},
{_id: '2', tags: [1, 2]}

Ответы [ 3 ]

1 голос
/ 08 июня 2019
db.inventory.aggregate([
  { $match : {tags : 'aaa' }},
  { $unwind : { path: "$tags", includeArrayIndex: "arrayIndex"}},
  { $match : {tags : 'aaa' }},
  { $group : {
      _id : '$_id',
      tags : { $push : '$arrayIndex'}
    }
  }
 ])

Выход:

{ "_id" : "2", "tags" : [ NumberLong(1), NumberLong(2) ] }
{ "_id" : "1", "tags" : [ NumberLong(0) ] }

Другой способ:

db.inventory.aggregate([
 { $match : {tags : 'aaa' }},
 { $project  : {
    tags: {
      $filter: {
        input: {
          $zip: {
            inputs: [ "$tags", { $range: [0, { $size: "$tags" }] } ]
          }
        },
        as: "tagWithIndex",
        cond: {
          $let: {
            vars: {
              tag : { $arrayElemAt: [ "$$tagWithIndex", 0 ] }
            },
            in: { $eq: [ "$$tag", 'aaa' ] }
          }
        }
      }
    }
 }},
 { $unwind  : '$tags'},
 { $group : {
       _id : '$_id',
       tags  : {
          $push : { $arrayElemAt: [ "$tags", 1]}
       }
   }
 }
])

Выход:

{ "_id" : "2", "tags" : [ 1, 2 ] }
{ "_id" : "1", "tags" : [ 0 ] }

надеюсь, это поможет.

1 голос
/ 08 июня 2019

Вам необходимо $map над $size массива $tags, чтобы включить индекс каждогоэлемент внутри массива tags, а затем вы можете легко использовать агрегацию $filter, чтобы исключить элементы, содержащие буквы aaa

db.collection.aggregate([
  { "$match": { "tags": "aaa" }},
  { "$project": {
    "tags": {
      "$filter": {
        "input": {
          "$map": {
            "input": { "$range": [0, { "$size": "$tags" }] },
            "in": {
              "string": { "$arrayElemAt": ["$tags", "$$this"] },
              "index": "$$this"
            }
          }
        },
        "cond": { "$eq": ["$$this.string", "aaa"] }
      }
    }
  }},
  { "$project": { "tags": "$tags.index" }}
])

Выход

[
  {
    "_id": "1",
    "tags": [0]
  },
  {
    "_id": "2",
    "tags": [1, 2]
  }
]
0 голосов
/ 08 июня 2019

Если вы ищете массив, вы должны использовать $ in.

db.inventory.find( { tags: { $in: [ 'aaa' ] } } )

Вы также можете написать то же самое в матче. орфография такая же.

Поможем для деталей. Это то, что вы ищете.

Источник: https://docs.mongodb.com/manual/reference/operator/query/in/


db.inventory.find( { "tags": { $in: 'aaa' } },
                  { "tags.$": 1 } )

Это, вероятно, то, что вы хотите.

...