sql >> Database >  >> NoSQL >> MongoDB

Zoek eerste element in geneste array dat overeenkomt met voorwaarden

Het beste is om te zoeken met $where naast de normale zoekopdracht, en bewaar dingen nog steeds op de server:

db.getCollection('collection').find({
  "array": {
    "$elemMatch": { "field": "BCD", "enabled": "true" },
  },
  "$where": function() {
    return this.array.map((e,i) => Object.assign(e,{ i }))
      .filter( e => e.field === "BCD" && e.enabled === "true" )
      .map( e => e.i )[0] <=
    this.array.map(e => e.enabled).indexOf("true")
  }  
})

En als je MongoDB 3.4 hebt met ondersteuning voor $indexOfArray en $range , dan lijkt het misschien langer, maar het is eigenlijk het meest efficiënt met $redact :

db.getCollection('collection').aggregate([
  { "$match": {
    "array": {
      "$elemMatch": { "field": "BCD", "enabled": "true" },
    }
  }},
  { "$redact": {
    "$cond": {  
      "if": {
        "$lte": [
          { "$arrayElemAt": [
            { "$map": {
              "input": {
                "$filter": {
                  "input": {
                    "$map": {
                      "input": {
                        "$zip": {
                          "inputs": [
                            "$array",
                            { "$range": [0, { "$size": "$array" }] }
                          ]
                        }    
                      },
                      "as": "a",
                      "in": {
                        "field": { "$arrayElemAt": [ "$$a.field", 0 ] },
                        "enabled": { "$arrayElemAt": [ "$$a.enabled", 0 ] },
                        "index": { "$arrayElemAt": [ "$$a", 1 ] }    
                      }
                    }
                  },
                  "as": "a",
                  "cond": {
                    "$and": [
                      { "$eq": [ "$$a.field", "BCD" ] },
                      { "$eq": [ "$$a.enabled", "true" ] }
                    ]
                  }    
                }
              },
              "as": "a",
              "in": "$$a.index"  
            }},
            0
          ]},
          { "$indexOfArray": [ "$array.enabled", "true" ] } 
        ] 
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Er is dus geen echte query-operatie die dat afdwingt, maar in beide gevallen blijft de selectie "op de server" staan ​​in plaats van gegevens over de kabel naar de client te sturen en vervolgens te filteren.

Want als je dat doet, ontken je het doel van het gebruik van een database in de eerste plaats. Dus je wilt echt dat dit op de server gebeurt.



  1. Mongo-aggregatie binnen tijdsintervallen

  2. Unieke index in mongoDB 3.2 negeert null-waarden

  3. Hoe kan ik sorteren op $elemMatch in MongoDB?

  4. Hoe indexeer je meerdere unieke gegevensvelden in een enkel document in Mongoose?