Mongodb 查找嵌套数组中匹配条件的第一个元素

Mongodb 查找嵌套数组中匹配条件的第一个元素,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有以下文件: doc1: { 'array': [ {'field': 'ABC', 'enabled': 'false'}, {'field': 'BCD', 'enabled': 'true'}, {'field': 'DEF', 'enabled': 'false'}, {'field': 'XYZ', 'enabled': 'true'}, ] } doc2: { 'array': [ {'field': 'ABC', 'en

我有以下文件:

doc1: { 
  'array': [
    {'field': 'ABC', 'enabled': 'false'},
    {'field': 'BCD', 'enabled': 'true'},
    {'field': 'DEF', 'enabled': 'false'},
    {'field': 'XYZ', 'enabled': 'true'},
  ]
}


doc2: { 
  'array': [
    {'field': 'ABC', 'enabled': 'true'},
    {'field': 'BCD', 'enabled': 'true'},
    {'field': 'DEF', 'enabled': 'false'},
    {'field': 'XYZ', 'enabled': 'true'},
  ]
}
我正在按特定字段执行搜索。 我想获取启用此字段的所有文档,并且在此之前(列表中)没有启用其他字段

例如:

搜索字段:
BCD
,enabled:true-应仅返回第一个文档(因为在第二个文档中,
ABC
也已启用)

搜索
XYZ
,enabled:true-不应返回任何文档,因为此列表顶部有其他启用的字段

我试图用
$elemMatch
进行smth,但我不知道是否可以在
elemMatch
匹配的元素上应用过滤器


有什么建议吗?

为什么不通过启用的
字段进行搜索,然后检查
字段是否合适

db.collection("col").findOne({
    "array.enabled": true
}, {
    array: {
        $elemMatch {
            enabled: true
        }
    }
})
.then(function(docs){
    docs.forEach(function(doc){
        if(doc.array[0].field == "ABC"){
            // Ok, we get it
        }
    })
})

find
的第二个参数是投影,所以应用程序不会从文档中下载完整的数组,而只下载它的第一个匹配元素。

$where
关键字,允许为类似目的生成复杂条件

find($where:'this.array.filter(函数(e){returne e.enabled==“true”})[0]。field==“ABC”)


由于这不使用任何索引,我将添加更多条件以从优化中获益。

除了使用常规查询外,最好使用搜索,并且仍将内容保留在服务器上:

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")
  }  
})
因此,实际上并没有实际的查询操作来强制执行该操作,但这两种情况都将选择保留在“服务器上”,而不是通过线路将数据发送到客户端,然后进行过滤

因为如果你这样做的话,首先就否定了使用数据库的目的。因此,您确实希望这种情况发生在服务器上

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