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

レコード内のフィールド数に基づくMongodbクエリ

    それでも実行するのに適したクエリではありませんが、 $ objectToArrayを介して実行するためのもう少し新しい方法があります。 および$redact

    db.collection.aggregate([
      { "$redact": {
        "$cond": {
          "if": {
            "$eq": [
              { "$size": { "$objectToArray": "$value" } },
              3
            ]
          },
          "then": "$$KEEP",
          "else": "$$PRUNE"
        }
      }}
    ])
    

    ここで、 $ objectToArray 基本的に、 Object.keys()の組み合わせのように、オブジェクトを配列形式に強制します および.map() JavaScriptで。

    コレクション全体をスキャンする必要があるため、まだ素晴らしいアイデアではありませんが、少なくとも集約フレームワークの操作では、 $ where を使用する場合のようにJavaScriptの解釈ではなく、「ネイティブコード」を使用します。 。

    したがって、最も効果的なクエリ操作を行うために、データ構造を変更し、自然な配列と、可能な場合は保存された「サイズ」プロパティを使用することをお勧めします。

    はい、それは可能ですが、最も良い方法ではありません。これは、基本的に $ where JavaScript評価を使用して内容を照合する演算子クエリ。これはインデックスを使用できず、すべてのドキュメントをテストする必要があるため、最も効率的な方法ではありません。

    db.collection.find({ "$where": "return Object.keys(this.value).length == 3" })
    

    これにより、「3つの」要素に一致する条件が検索され、リストされたドキュメントのうち2つだけが返されます。

    { "_id" : "number1", "value" : { "a" : 1, "b" : 2, "f" : 5 } }
    { "_id" : "number2", "value" : { "e" : 2, "f" : 114, "h" : 12 } }
    

    または、「5」以上のフィールドについても、ほぼ同じことができます。

    db.numbers.find({ "$where": "return Object.keys(this.value).length >= 5" })
    

    したがって、その演算子への引数は、事実上、サーバー上で評価されて trueを返すJavaScriptステートメントです。 。

    より効率的な方法は、要素の「カウント」をドキュメント自体に格納することです。このようにして、このフィールドに「インデックスを付ける」ことができ、他の条件で選択されたコレクション内の各ドキュメントをスキャンして長さを決定する必要がないため、クエリがはるかに効率的になります。

    {_id:'number1', value:{'a':1, 'b':2, 'f':5} count: 3},
    {_id:'number2', value:{'e':2, 'f':114, 'h':12}, count: 3},
    {_id:'number3', value:{'i':2, 'j':22, 'z':12, 'za':111, 'zb':114}, count: 5}
    

    次に、「5つの」要素を含むドキュメントを取得するには、単純なクエリのみが必要です。

    db.collection.find({ "count": 5 })
    

    これが一般的に最適な形式です。しかし、もう1つのポイントは、一般的な慣習から満足できる一般的な「オブジェクト」構造は、MongoDBが一般的に「うまく機能する」ものではないということです。問題は、オブジェクト内の要素の「トラバーサル」です。このように、「配列」を使用すると、MongoDBの方がはるかに幸せです。そしてこの形でも:

    {
        '_id': 'number1', 
        'values':[
            { 'key': 'a', 'value': 1 },
            { 'key': 'b', 'value': 2 }, 
            { 'key': 'f', 'value': 5 }
        ],
    },
    {
        '_id': 'number2', 
        'values':[
            { 'key': 'e', 'value': 2 }, 
            { 'key': 'f', 'value': 114 }, 
            { 'key': 'h', 'value': 12 }
        ],
    },
    {
        '_id':'number3', 
        'values': [
            { 'key': 'i', 'values': 2 }, 
            { 'key': 'j', 'values': 22 }, 
            { 'key': 'z'' 'values': :12 }, 
            { 'key': 'za', 'values': 111 },
            { 'key': 'zb', 'values': 114 }
        ]
    }
    

    したがって、実際にそのような「配列」形式に切り替えると、正確なを実行できます。 $の1つのバージョンを含む配列の長さサイズ 演算子:

    db.collection.find({ "values": { "$size": 5 } })
    

    そのオペレーターは正確なのために働くことができます 配列の長さの値は、この演算子で実行できることの基本的な規定です。 「不平等」の試合で文書化されているように、あなたができないこと。そのためには、MongoDBの「集約フレームワーク」が必要です。これは、JavaScriptおよびmapReduce操作のより優れた代替手段です:

    db.collection.aggregate([
        // Project a size of the array
        { "$project": {
            "values": 1,
            "size": { "$size": "$values" }
        }},
        // Match on that size
        { "$match": { "size": { "$gte": 5 } } },
        // Project just the same fields 
        {{ "$project": {
            "values": 1
        }}
    ])
    

    だからそれらは代替です。集計と配列型に使用できる「ネイティブ」メソッドがあります。しかし、JavaScriptの評価もMongoDBに対して「ネイティブ」であり、したがってネイティブコードに実装されていないことはかなり議論の余地があります。



    1. Redis-値がアクティブに書き込まれなくなったときにイベントをトリガーする方法はありますか?

    2. レプリカセットへのマングース接続

    3. MongoDB-特定のExplain出力を解釈します

    4. Redisの名前空間?