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

mongodbの複数の制限条件

    一般的に、あなたが説明しているのは、MongoDBコミュニティで比較的よくある質問であり、「トップn」と表現できます。 結果の問題」。これは、何らかの方法で並べ替えられている可能性のある入力が与えられた場合に、上位のnを取得する方法です。 データ内の任意のインデックス値に依存せずに結果が得られます。

    MongoDBには、 $firstがあります。 集約フレームワーク で使用できる演算子 これは、問題の「トップ1」の部分を処理します。これは、実際には、「タイプ」などのグループ化境界で見つかった「最初の」アイテムを取得するためです。しかし、もちろん、「1つ」以上の結果を得るには、もう少し複雑になります。 nを処理するために他の演算子を変更することに関して、これにはいくつかのJIRAの問題があります。 結果または「制限」または「スライス」。特に SERVER-6074 。ただし、問題はいくつかの方法で処理できます。

    MongoDBストレージのrailsActiveRecordパターンの一般的な実装は、Mongoid です。 および Mongo Mapper 、どちらも.collectionを介して「ネイティブ」mongodbコレクション関数へのアクセスを許可します アクセサー。これは、基本的に .aggregate() これは、一般的なActiveRecord集約よりも多くの機能をサポートします。

    これがmongoidを使用した集約アプローチですが、ネイティブコレクションオブジェクトにアクセスできるようになると、一般的なコードは変更されません。

    require "mongoid"
    require "pp";
    
    Mongoid.configure.connect_to("test");
    
    class Item
      include Mongoid::Document
      store_in collection: "item"
    
      field :type, type: String
      field :pos, type: String
    end
    
    Item.collection.drop
    
    Item.collection.insert( :type => "A", :pos => "First" )
    Item.collection.insert( :type => "A", :pos => "Second"  )
    Item.collection.insert( :type => "A", :pos => "Third" )
    Item.collection.insert( :type => "A", :pos => "Forth" )
    Item.collection.insert( :type => "B", :pos => "First" )
    Item.collection.insert( :type => "B", :pos => "Second" )
    Item.collection.insert( :type => "B", :pos => "Third" )
    Item.collection.insert( :type => "B", :pos => "Forth" )
    
    res = Item.collection.aggregate([
      { "$group" => {
          "_id" => "$type",
          "docs" => {
            "$push" => {
              "pos" => "$pos", "type" => "$type"
            }
          },
          "one" => {
            "$first" => {
              "pos" => "$pos", "type" => "$type"
            }
          }
      }},
      { "$unwind" =>  "$docs" },
      { "$project" => {
        "docs" => {
          "pos" => "$docs.pos",
          "type" => "$docs.type",
          "seen" => {
            "$eq" => [ "$one", "$docs" ]
          },
        },
        "one" => 1
      }},
      { "$match" => {
        "docs.seen" => false
      }},
      { "$group" => {
        "_id" => "$_id",
        "one" => { "$first" => "$one" },
        "two" => {
          "$first" => {
            "pos" => "$docs.pos",
            "type" => "$docs.type"
          }
        },
        "splitter" => {
          "$first" => {
            "$literal" => ["one","two"]
          }
        }
      }},
      { "$unwind" => "$splitter" },
      { "$project" => {
        "_id" => 0,
        "type" => {
          "$cond" => [
            { "$eq" => [ "$splitter", "one" ] },
            "$one.type",
            "$two.type"
          ]
        },
        "pos" => {
          "$cond" => [
            { "$eq" => [ "$splitter", "one" ] },
            "$one.pos",
            "$two.pos"
          ]
        }
      }}
    ])
    
    pp res
    

    ドキュメントの名前は実際にはコードで使用されていません。「First」、「Second」などに表示されるデータのタイトルは、実際にリストから「トップ2」のドキュメントを取得していることを示すためのものです。結果。

    したがって、ここでのアプローチは、基本的に、「タイプ」などのキーによって「グループ化」されたドキュメントの「スタック」を作成することです。ここで最初に行うことは、 $first オペレーター。

    以降の手順では、スタックから「表示された」要素を照合してフィルタリングし、 $first オペレーター。そこにある最後のステップは、実際には、入力で見つかった元の形式にドキュメントを戻すためのjustxです。これは、通常、そのようなクエリから期待されるものです。

    したがって、結果はもちろん、各タイプの上位2つのドキュメントのみです。

    { "type"=>"A", "pos"=>"First" }
    { "type"=>"A", "pos"=>"Second" }
    { "type"=>"B", "pos"=>"First" }
    { "type"=>"B", "pos"=>"Second" }
    

    この最近の回答には、これと他の解決策のより長い議論とバージョンがありました:

    Mongodbアグリゲーション$group、配列の長さを制限

    タイトルにもかかわらず本質的に同じことであり、その場合は最大10以上の上位エントリに一致することを探していました。そこには、より大きな一致を処理するためのパイプライン生成コードや、データに応じて検討される可能性のあるいくつかの代替アプローチもあります。



    1. ソートされたセットRedisをどのように組み合わせるのですか?

    2. SpringBootFrameworkでJedisConnectionFactoryベースのタイムアウトを構成する方法

    3. 接続時のNodeJS+マングースタイムアウト

    4. monogdbの$facet集約