sql >> データベース >  >> NoSQL >> MongoDB

$slice演算子を使用して配列の最後の要素を取得する

    ご存知のとおり、$ Sliceは、結果で返される配列要素を制限するための射影でのみ使用されます。そのため、find()の結果を使用してプログラムでリストを処理することに固執することになります。

    より良いアプローチは、集計を使用することです。ただし、最初に $ slaveについて考えてみましょう。 使用される:

    > db.collection.find({},{ relevancy: {$slice: -1} })
    { "_id" : ObjectId("530824b95f44eac1068b45c0"), "relevancy" : [  "Y" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c2"), "relevancy" : [  "Y" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c3"), "relevancy" : [  "N" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c4"), "relevancy" : [  "Y" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c6"), "relevancy" : [  "N" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c7"), "relevancy" : [  "N" ] }
    { "_id" : ObjectId("530824b95f44eac1068b45c8"), "relevancy" : [  "N" ] }
    

    したがって、最後の配列要素を取得しますが、一致できないため、結果のループにとどまります。 最後の要素の値。これをコードで行った方がよいでしょう。

    それでは、集計を見てみましょう。 :

    db.collection.aggregate([
        // Match things so we get rid of the documents that will never match, but it will
        // still keep some of course since they are arrays, that *may* contain "N"
        { "$match": { "relevancy": "Y" } },
    
        // De-normalizes the array
        { "$unwind": "$relevancy" },
    
        // The order of the array is retained, so just look for the $last by _id
        { "$group": { "_id": "$_id", "relevancy": { "$last": "$relevancy" } }},
    
        // Match only the records with the results you want
        { "$match": { "relevancy": "Y" }},
    
        // Oh, and maintain the original _id order [ funny thing about $last ]
        { "$sort": { "_id": 1 } }
    ])
    

    これがaggregate()の最初の使用法である場合でも、学ぶことをお勧めします。 。それはおそらくあなたの最も有用な問題解決ツールです。確かに私にとってはそうです。各ステップを1回に入れます 一度に学習している場合。

    また、ドキュメントフォームで、すべての1: { ... }がわからない サブドキュメントの表記は間違いのようですが、それをクリアするか、上記のコードを調整して"1.relevancy"を参照する必要があります。 代わりは。ただし、実際にはドキュメントが次のようになっていることを願っています:

    { "relevancy" : [  "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c0") }
    { "relevancy" : [  "Y",  "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c2") }
    { "relevancy" : [  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c3") }
    { "relevancy" : [  "Y",  "Y" ], "_id" : ObjectId("530824b95f44eac1068b45c4") }
    { "relevancy" : [  "Y",  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c6") }
    { "relevancy" : [  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c7") }
    { "relevancy" : [  "Y",  "N" ], "_id" : ObjectId("530824b95f44eac1068b45c8") }
    

    MongoDB3.2.x以降

    もちろん、MongoDB 3.2では、$sliceに「aggregation」演算子が導入されています。 さらに優れた$arrayElemAt $unwindの必要性を排除する演算子 および$group 処理。最初の$matchの後 $redactと「論理的に一致」するだけのクエリ :

    db.collection.aggregate([
        { "$match": { "relevancy": "Y" } },
        { "$redact": {
            "$cond": {
                "if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
                "then": "$$KEEP",
                "else": "$$PRUNE"
            }
        }}   
    ])
    

    これにより、$$KEEPを実行するかどうかを決定するときに、配列の最後の要素が検査されます。 または$$PRUNE 返された結果からのドキュメント。

    それでも「プロジェクション」が必要な場合は、実際に$sliceを追加できます。 :

    db.collection.aggregate([
        { "$match": { "relevancy": "Y" } },
        { "$redact": {
            "$cond": {
                "if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
                "then": "$$KEEP",
                "else": "$$PRUNE"
            }
        }},
        { "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } }
    ])
    

    または、次の代替アプローチ:

    db.collection.aggregate([
        { "$match": { "relevancy": "Y" } },
        { "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
        { "$match": { "relevancy": "Y" } }
    ])
    

    ただし、$redactを実行する方がおそらくコストがかかりません。 最初に「次に」、`$projectで再形成を行います。



    1. ネストされた配列内のMongodbインクリメント値

    2. レール環境をロードせずにrubyresque

    3. RedisAOFとTarantoolWALログの違い

    4. AWS ElastiCacheでメモリ分析を実行する方法は?