sql >> Database teknologi >  >> NoSQL >> MongoDB

Find i Double Nested Array MongoDB

I den enkleste forstand følger dette bare den grundlæggende form for "punktnotation", som bruges af MongoDB. Det fungerer uanset hvilket array-medlem det indre array-medlem er i, så længe det matcher en værdi:

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

Det er fint for en "enkelt felt"-værdi, for at matche flere felter ville du bruge $elemMatch :

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

Det matcher det dokument, der ville indeholde noget med et a-felt ved den "sti", der matcher værdien. Hvis du havde til hensigt at "matche og filtrere" resultatet, så kun det matchede element blev returneret, er dette ikke muligt med den positionelle operatorprojektion, som citeret:

Indlejrede arrays

Den positionelle $-operator kan ikke bruges til forespørgsler, der krydser mere end ét array, såsom forespørgsler, der krydser arrays indlejret i andre arrays, fordi erstatningen for $-pladsholderen er en enkelt værdi

Moderne MongoDB

Vi kan gøre dette ved at anvende $filter og $map her. $map er virkelig nødvendig, fordi det "indre" array kan ændre sig som et resultat af "filtreringen", og det "ydre" array matcher selvfølgelig ikke betingelserne, da det "indre" blev strippet for alle elementer.

Igen følger eksemplet med faktisk at have flere egenskaber, der skal matche inden for hvert 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 ] }
          ]
        }
      }
    }
  }}
])

Derfor er $filter på det "ydre" array ser faktisk på $size af det "indre" array, efter at det selv blev "filtreret", så du kan afvise disse resultater, når hele det indre array faktisk matcher notering.

Ældre MongoDB

For kun at "projektere" det matchede element, skal du bruge .aggregate() metode:

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 giver dig mulighed for at "filtrere" kampene i indlejrede arrays for et eller flere resultater i dokumentet.



  1. Brug mongoexport med en --query for ISODate

  2. WRONGTYPE Operation mod en tast med den forkerte slags værdi php

  3. Returner det sidste dokument fra et opslag

  4. Logstash Web UI starter ikke