MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Localizar no array aninhado duplo MongoDB


No sentido mais simples, isso apenas segue a forma básica de "notação de ponto" usada pelo MongoDB. Isso funcionará independentemente do membro da matriz em que o membro da matriz interna esteja, desde que corresponda a um valor:
db.mycollection.find({
    "someArray.someNestedArray.name": "value"
})

Isso é bom para um valor de "campo único", para corresponder a vários campos, você usaria $elemMatch :
db.mycollection.find({
    "someArray": { 
        "$elemMatch": {
            "name": "name1",
            "someNestedArray": {
                "$elemMatch": {
                    "name": "value",
                    "otherField": 1
                }
            }
        }
    }
})

Isso corresponde ao documento que conteria algo com um campo nesse "caminho" correspondente ao valor. Se você pretendia "combinar e filtrar" o resultado para que apenas o elemento correspondido fosse retornado, isso não é possível com a projeção do operador posicional, conforme citado:

Matrizes aninhadas

O operador posicional $ não pode ser usado para consultas que percorrem mais de uma matriz, como consultas que percorrem matrizes aninhadas em outras matrizes, porque a substituição do espaço reservado $ é um valor único

MongoDB moderno


Podemos fazer isso aplicando $filter e $map aqui. O $map é realmente necessário porque o array "interno" pode mudar como resultado da "filtragem", e o array "externo" obviamente não corresponde às condições quando o "interno" foi retirado de todos os elementos.

Novamente seguindo o exemplo de realmente ter várias propriedades para corresponder em cada matriz:
db.mycollection.aggregate([
  { "$match": {
    "someArray": {
      "$elemMatch": {
         "name": "name1",
         "someNestedArray": {
           "$elemMatch": {
             "name": "value",
             "otherField": 1
           }
         }
       }
    }
  }},
  { "$addFields": {
    "someArray": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$someArray",
            "as": "sa",
            "in": {
              "name": "$$sa.name",
              "someNestedArray": {
                "$filter": {
                  "input": "$$sa.someNestedArray",
                  "as": "sn",
                  "cond": {
                    "$and": [
                      { "$eq": [ "$$sn.name", "value" ] },
                      { "$eq": [ "$$sn.otherField", 1 ] }
                    ]
                  }
                }
              }             
            }
          },
        },
        "as": "sa",
        "cond": {
          "$and": [
            { "$eq": [ "$$sa.name", "name1" ] },
            { "$gt": [ { "$size": "$$sa.someNestedArray" }, 0 ] }
          ]
        }
      }
    }
  }}
])

Portanto, no array "externo" o $filter realmente olha para o $size da matriz "interna" depois que ela foi "filtrada", para que você possa rejeitar esses resultados quando toda a matriz interna de fato corresponder à observação.

MongoDB mais antigo


Para "projetar" apenas o elemento correspondente, você precisa do .aggregate() método:
db.mycollection.aggregate([
    // Match possible documents
    { "$match": {
        "someArray.someNestedArray.name": "value"
    }},

    // Unwind each array
    { "$unwind": "$someArray" },
    { "$unwind": "$someArray.someNestedArray" },

    // Filter just the matching elements
    { "$match": {
        "someArray.someNestedArray.name": "value"
    }},

    // Group to inner array
    { "$group": {
        "_id": { 
            "_id": "$_id", 
            "name": "$someArray.name"
        },
        "someKey": { "$first": "$someKey" },
        "someNestedArray": { "$push": "$someArray.someNestedArray" }
    }},

    // Group to outer array
    { "$group": {
        "_id": "$_id._id",
        "someKey": { "$first": "$someKey" },
        "someArray": { "$push": {
            "name": "$_id.name",
            "someNestedArray": "$someNestedArray"
        }}
    }} 
])

Isso permite que você "filtre" as correspondências em matrizes aninhadas para um ou mais resultados no documento.