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

最後の配列エントリフィールド値で結果をフィルタリングする

    マイレージはこれによって異なる場合があり、「現在」あなたがフォローしているプロセスが少なくとも「最も適している」ことが判明する可能性があります。しかし、おそらくもっと効率的にすることができます。

    今できること

    $ sort $ pushを使用した修飾子 、その後、おそらくこれを行うことができます:

    db.somedb.find(
      { 
        "partn.is_partner": true,
        "$where": function() {
          return this.partn.slice(-1)[0].is_partner == true;
        }
      },
      { "partn": { "$slice": -1 } }
    )
    

    partn、is_partnerである限り は「インデックス付き」であり、インデックスを使用して初期クエリ条件を満たすことができるため、これは依然としてかなり効率的です。できない部分は、 $ where ここではJavaScript評価を使用する句。

    しかし、 $ whereの2番目の部分は何ですか 実行しているのは、配列から最後の要素を単に「スライス」し、その値を is_partnerでテストすることです。 それが本当かどうかを確認するためのプロパティ。その条件も満たされている場合にのみ、ドキュメントが返されます。

    $ slaveもあります。 射影演算子。これは、配列から最後の要素を返す場合にも同じことを行います。偽の一致はすでにフィルタリングされているため、これは真の最後の要素のみを表示しています。

    前述のようにインデックスと組み合わせると、ドキュメントがすでに選択されており、JavaScript条件が残りをフィルタリングするだけであるため、これは非常に迅速です。一致する標準のクエリ条件を持つ別のフィールドがない場合、 $ where 句はインデックスを使用できません。したがって、他のクエリ条件を設定した状態で、常に「控えめに」使用するようにしてください。

    将来できること

    Next Upは、執筆時点では利用できませんが、近い将来、 $ slaveになることは間違いありません。 集約フレームワークの演算子。これは現在開発ブランチにありますが、これがどのように機能するかを見てみましょう:

    db.somedb.aggregate([
      { "$match": { "partn.is_partner": true } },
      { "$redact": {
        "$cond": {
          "if": { 
            "$anyElementTrue": {
              "$map": {
                "input": { "$slice": ["$partn",-1] },
                "as": "el",
                "in": "$$el.is_partner"
              }
            }
          },
          "then": "$$KEEP",
          "else": "$$PRUNE"
        }
      }},
      { "$project": {
          "partn": { "$slice": [ "$partn",-1 ] }
      }}
    ])
    

    その$辛いを組み合わせる $ redact ここでのステ​​ージでは、ドキュメントを論理条件でフィルタリングし、ドキュメントをテストします。この場合、 $ sense $に送信される単一要素配列を生成しますマップ 単一のis_partnerを抽出するために 値(まだ配列として)。これはまだせいぜい単一要素の配列であるため、他のテストは <強い>$ anyElementTrue これは、 に適した、特異なブール結果になります。 $ cond

    $ redact ここで、その結果を $$ KEEPするかどうかを決定します または$$PRUNE 結果からのドキュメント。後で$senseを使用します プロジェクトで再度、フィルタリング後に配列の最後の要素を返すだけです。

    これは、すべてのネイティブコード化演算子を使用していることを除いて、JavaScriptバージョンとほぼ同じであることがわかります。したがって、JavaScriptの代替よりも少し高速である必要があります。

    どちらのフォームも、最初のドキュメントを期待どおりに返します:

    {
        "_id" : 0,
        "partn" : [
                {
                        "date" : ISODate("2015-07-28T00:59:14.963Z"),
                        "is_partner" : true
                },
                {
                        "date" : ISODate("2015-07-28T01:00:32.771Z"),
                        "is_partner" : false
                },
                {
                        "date" : ISODate("2015-07-28T01:15:29.916Z"),
                        "is_partner" : true
                },
                {
                        "date" : ISODate("2015-08-05T13:48:07.035Z"),
                        "is_partner" : false
                },
                {
                        "date" : ISODate("2015-08-05T13:50:56.482Z"),
                        "is_partner" : true
                }
        ]
    }
    

    ここでの両方の大きな問題は、配列がすでにソートされている必要があるため、最新の日付が最初になることです。それがなければ、 $ sortへの集約フレームワークが必要です。 今行っているのと同じように、アレイ。

    あまり効率的ではないため、アレイを「事前に並べ替え」て、更新のたびに順序を維持する必要があります。

    便利なトリックとして、これにより、すべてのコレクションドキュメント内のすべての配列要素が1つの簡単なステートメントで実際に並べ替えられます。

    db.somedb.update(
        {},
        { "$push": { 
            "partn": { "$each": [], "$sort": { "date": 1 } }
        }},
        { "multi": true }
    )
    

    したがって、新しい要素を配列に「プッシュ」してプロパティを更新するだけでなくても、いつでもその基本的な構成を適用して、配列を希望どおりに順序付けておくことができます。

    物事をはるかに速くするはずなので、検討する価値があります。




    1. Linuxにmongodbをインストールできません

    2. spring-data-redis1.7.0.M1を使用するときにredis-clusterを設定する方法

    3. _idフィールドのないmongoexport

    4. 管理者以外のユーザーのmongoDBユーザーパスワードを変更するにはどうすればよいですか?