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

Mongodbアグリゲーションパイプラインで正規表現を使用できるようにするための回避策はありますか?

    この質問は解決策なしで何度も出てくるようです。私が知っている2つの可能な解決策があります:解決策1-mapReduceを使用します。 mapReduceは、ユーザーが想像でき、プログラム可能なことを何でもできるようにする集計の一般的な形式です。

    以下は、mapReduceを使用したmongoシェルソリューションです。次の「st」コレクションを検討します。

    { "_id" : ObjectId("51d6d23b945770d6de5883f1"), "foo" : "foo1", "bar" : "bar1" }
    { "_id" : ObjectId("51d6d249945770d6de5883f2"), "foo" : "foo2", "bar" : "bar2" }
    { "_id" : ObjectId("51d6d25d945770d6de5883f3"), "foo" : "foo2", "bar" : "bar22" }
    { "_id" : ObjectId("51d6d28b945770d6de5883f4"), "foo" : "foo2", "bar" : "bar3" }
    { "_id" : ObjectId("51d6daf6945770d6de5883f5"), "foo" : "foo3", "bar" : "bar3" }
    { "_id" : ObjectId("51d6db03945770d6de5883f6"), "foo" : "foo4", "bar" : "bar24" }
    

    fooでグループ化し、各fooについて、ドキュメントの数と、サブ文字列'bar2'を含むbarを持つドキュメントの数をカウントします。つまり:

    foo1: nbdoc=1, n_match = 0
    foo2: nbdoc=3, n_match = 2
    foo3: nbdoc=1, n_match = 0
    foo4: nbdoc=1, n_match = 1
    

    そのためには、次のマップ関数を定義します

    var mapFunction = function() {
      var key = this.foo;
      var nb_match_bar2 = 0;
      if( this.bar.match(/bar2/g) ){
        nb_match_bar2 = 1;
      }
      var value = {
        count: 1,
        nb_match: nb_match_bar2
      };
    
      emit( key, value );
    };
    

    および次のreduce関数

    var reduceFunction = function(key, values) {
    
      var reducedObject = {
        count: 0,
        nb_match:0
      };
      values.forEach( function(value) {
        reducedObject.count += value.count;
        reducedObject.nb_match += value.nb_match;
      }
      );
      return reducedObject;
    };
    

    mapduceを実行し、結果をコレクションmap_reduce_result

    に保存します
    db.st.mapReduce(mapFunction, reduceFunction, {out:'map_reduce_result'})
    {
      "result" : "map_reduce_result",
      "timeMillis" : 7,
      "counts" : {
        "input" : 6,
        "emit" : 6,
        "reduce" : 1,
        "output" : 4
    },
    "ok" : 1,
    }
    

    最後に、コレクションmap_reduce_resultをクエリできます。ソリューション

    > db.map_reduce_result.find()
    { "_id" : "foo1", "value" : { "count" : 1, "nb_match" : 0 } }
    { "_id" : "foo2", "value" : { "count" : 3, "nb_match" : 2 } }
    { "_id" : "foo3", "value" : { "count" : 1, "nb_match" : 0 } }
    { "_id" : "foo4", "value" : { "count" : 1, "nb_match" : 1 } }
    

    解決策2-2つの別々の集計とマージを使用するmongoユーザーなら誰でも簡単に実行できるため、このソリューションの詳細は説明しません。手順1:正規表現を合計する必要がある部分を無視して集計を実行します。手順2:2番目の集計グループ化を実行します。ステップ1のキーと同じキー上。パイプラインのステージ1:正規表現に一致します。ステージ2:最初のステップと同じキーでグループ化し、各グループのドキュメント数をカウントします{$ sum:1};ステップ3:ステップ1と2の結果をマージします。両方の結果に表示されるキーごとに、新しいフィールドを追加します。2番目の結果にキーが存在しない場合は、新しいキーを0に設定します。

    出来上がり!別の解決策。




    1. MongoDBは同時更新をどのように処理しますか?

    2. クエリが正しく機能しない状態でforEach内にプッシュ

    3. Nodejs + Mongo dbは、ユーザー名とパスワードを使用してサーバーデータベースに接続します

    4. 流星開発で外部mongodbを使用する