MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comparer le document intégré au champ parent avec mongoDB

Les requêtes standard ne peuvent pas "comparer" les valeurs dans les documents. C'est en fait quelque chose que vous faites en utilisant .aggregate() et $redact :

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

Ici, nous utilisons $filter pour comparer les valeurs de "amount" dans le document parent à ceux du tableau. Si au moins un est "égal" alors nous "$$KEEP" le document, sinon nous "$$PRUNE"

Dans les versions les plus récentes, nous pouvons raccourcir cela en utilisant $indexOfArray .

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

Si vous ne vouliez en fait que les "éléments de tableau correspondants", vous ajouteriez un $filter en projection :

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

Mais le grand principe est bien entendu de "réduire" le nombre de documents retournés à uniquement ceux qui correspondent réellement à la condition en tant que "première" priorité. Sinon, vous ne faites que des calculs inutiles et un travail qui prend du temps et des ressources, pour des résultats que vous abandonneriez plus tard.

Donc "filtrer" en premier, et "remodeler" ensuite en priorité.