2017-08-17 10 views
2

に一致するネストされた配列の最初の要素を検索します。 私は、このフィールドが有効になっているすべての文書を取得したい、と(リストに)この前に有効に他のフィールドがありません。 EXのために私は以下のドキュメントをしている条件

:フィールドの

検索:BCD、有効:真 - (第2の文書にABCがあまりにも有効になっているため)のみ最初の文書を返す必要があります。

XYZを検索すると、true:このリストの上に他のフィールドが有効になっているため、ドキュメントを返さないでください。

$elemMatchでsmthを実行しようとしていましたが、elemMatchがマッチした要素の上にフィルタを適用できるかどうかわかりません。

提案がありますか?

答えて

0

同様の目的のために複雑な条件を生成することを可能にする$whereキーワードがあります。

find($where: 'this.array.filter(function(e){return e.enabled=="true"})[0].field=="ABC"')

これは、すべてのインデックスを使用していないとして、私は最適化の恩恵を受けるために多くの条件を追加します。

1

なぜenabledフィールドで検索してfieldが適切であるかどうかをチェックしませんか? find

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

第二引数が投影され、そのアプリケーションは、文書から完全な配列をダウンロードするが、唯一の最初のそれの要素にマッチしません。

3

おそらく通常のクエリに加えて$whereを使用して検索し、まだサーバ上で物事を保つためにベスト:

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

そして、あなたは$indexOfArray$rangeをサポートするMongoDBの3.4を持っている場合、それは長く見えるかもしれませんしかし実際には、最も効率的な$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" 
    } 
    }} 
]) 

本当にことを強制する実際のクエリ操作はありませんが、これらの例の両方がOPPOとして「サーバー上の」選択を保ちます電線を介してクライアントにデータを送信してからフィルタリングすることに従事しました。

あなたがしなければ、それは一種の最初の場所でデータベースを使用する目的を否定するということなので。だからあなたは本当にこれがサーバー上で起こることを望んでいます。

関連する問題