sql >> Databasteknik >  >> NoSQL >> MongoDB

Jämför inbäddat dokument med överordnat fält med mongoDB

Standardfrågor kan inte "jämföra" värden i dokument. Detta är faktiskt något du gör med .aggregate() och $redact :

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": {
            "$filter": {
              "input": "$offers",
              "as": "o",
              "cond": { "$eq": [ "$$o.amount", "$amount" ] }
            }
          }},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Här använder vi $filter för att jämföra värdena för "amount" i det överordnade dokumentet till de inom arrayen. Om minst en är "lika" så "$$KEEP" dokumentet, annars "$$PRUNE"

I de senaste versionerna kan vi förkorta det med $indexOfArray .

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$ne": [
          { "$indexOfArray": [ "$offers.amount", "$amount" ] },
          -1
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Om du faktiskt bara ville ha "matchande arrayelement" också, då skulle du lägga till en $filter i projektion:

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": {
            "$filter": {
              "input": "$offers",
              "as": "o",
              "cond": { "$eq": [ "$$o.amount", "$amount" ] }
            }
          }},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$project": {
    "amount": 1,
    "offers": {
      "$filter": {
        "input": "$offers",
        "as": "o",
        "cond": { "$eq": [ "$$o.amount", "$amount" ] }
      }
    }
  }}
])

Men huvudprincipen är förstås att "minska" antalet dokument som returneras till endast de som faktiskt matchar villkoret som en "första" prioritet. Annars gör du bara onödiga beräkningar och arbete som tar tid och resurser, för resultat som du senare skulle förkasta.

Så "filtrera" först och "omforma" sedan som en prioritet.



  1. Fylla på Ref i mongoose-schemat medan du arbetar med Graphql

  2. Node.js MongoDB Hitta med projektion för att utesluta _id returnerar det fortfarande

  3. Hur man får detta resultat med aggregat i mongoDB

  4. Vilken Mongo-instans i Replica Set anropade applikationen?