sql >> Databasteknik >  >> NoSQL >> MongoDB

Hitta i Double Nested Array MongoDB

I den enklaste meningen följer detta bara den grundläggande formen av "punktnotation" som används av MongoDB. Det kommer att fungera oavsett vilken array-medlem den inre array-medlemmen är i, så länge den matchar ett värde:

db.mycollection.find({
    "someArray.someNestedArray.name": "value"
})

Det är bra för ett "single field"-värde, för att matcha flera fält skulle du använda $elemMatch :

db.mycollection.find({
    "someArray": { 
        "$elemMatch": {
            "name": "name1",
            "someNestedArray": {
                "$elemMatch": {
                    "name": "value",
                    "otherField": 1
                }
            }
        }
    }
})

Det matchar dokumentet som skulle innehålla något med ett a-fält vid den "sökvägen" som matchar värdet. Om du tänkte "matcha och filtrera" resultatet så att bara det matchade elementet returnerades, är detta inte möjligt med positionsoperatorprojektionen, som citerat:

Inkapslade arrayer

Den positionella $-operatorn kan inte användas för frågor som går igenom mer än en array, till exempel frågor som korsar arrayer kapslade i andra arrayer, eftersom ersättningen för $-platshållaren är ett enda värde

Modern MongoDB

Vi kan göra detta genom att använda $filter och $map här. $map behövs verkligen eftersom den "inre" matrisen kan förändras som ett resultat av "filtreringen", och den "yttre" matrisen matchar naturligtvis inte villkoren när den "inre" togs bort från alla element.

Återigen följer exemplet med att faktiskt ha flera egenskaper att matcha inom varje array:

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 ] }
          ]
        }
      }
    }
  }}
])

Därför $filter i den "yttre" arrayen tittar faktiskt på $size av den "inre" matrisen efter att den "filtrerades" själv, så att du kan avvisa dessa resultat när hela den inre matrisen faktiskt matchar noteringen.

Äldre MongoDB

För att bara "projicera" det matchade elementet behöver du .aggregate() metod:

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"
        }}
    }} 
])

Det gör att du kan "filtrera" matchningarna i kapslade arrayer för ett eller flera resultat i dokumentet.



  1. Hur frågar jag efter dokument med _id-fältet i Java mongodb-drivrutinen?

  2. Automatisera databaskonfigurationskontroll

  3. Att avgöra varför Redis tar emot en SIGTERM varannan minut

  4. misslyckades med fel 10068:ogiltig operator:$oid