sql >> Base de Datos >  >> NoSQL >> MongoDB

Compare el documento incrustado con el campo principal con mongoDB

Las consultas estándar no pueden "comparar" valores en documentos. En realidad, esto es algo que haces usando .aggregate() y $redact :

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

Aquí usamos $filter para comparar los valores de "amount" en el documento padre a aquellos dentro de la matriz. Si al menos uno es "igual", entonces "$$KEEP" el documento, de lo contrario "$$PRUNE"

En las versiones más recientes, podemos acortarlo usando $indexOfArray .

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

Si en realidad solo quisiera los "elementos de matriz coincidentes", entonces agregaría un $filter en proyección:

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

Pero el principio fundamental es, por supuesto, "reducir" el número de documentos devueltos a solo aquellos que realmente cumplen la condición como una "primera" prioridad. De lo contrario, solo está haciendo cálculos y trabajos innecesarios que consumen tiempo y recursos, para obtener resultados que luego descartaría.

Así que "filtrar" primero y "remodelar" segundo como prioridad.