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

キー値を共有するMongoDBで2つのドキュメントを検索する

    私はあなたの質問の言い回しが実際にはあなたが抱えている特定の問題に関連しているとは思わないというコメントを支持しますが、MongoDBタイプのソリューションにおける慣用的なSQLの方法を説明します。実際の解決策は異なると思いますが、その問題は提示されておらず、SQLのみが提示されています。

    したがって、次のドキュメントをサンプルセットと見なし、わかりやすくするためにこのリストの_idフィールドを削除します。

    { "name" : "a", "type" : "b" }
    { "name" : "a", "type" : "c" }
    { "name" : "b", "type" : "c" }
    { "name" : "b", "type" : "a" }
    { "name" : "a", "type" : "b" }
    { "name" : "b", "type" : "c" }
    { "name" : "f", "type" : "e" }
    { "name" : "z", "type" : "z" }
    { "name" : "z", "type" : "z" }
    

    同じデータに対して提示されたSQLを実行すると、次の結果が得られます。

    a|b
    a|c
    a|c
    b|c
    b|a
    b|a
    a|b
    b|c
    

    2つのドキュメントが一致していないことがわかり、SQL操作のロジックを理解できます。つまり、別の言い方をすれば、「「名前」のキーが与えられたドキュメントは実行です。 1つ以上 キー「タイプ」の可能な値。

    それを考えると、mongoアプローチを使用して、しないアイテムをクエリできます。 与えられた条件に一致します。だから効果的にリバース 結果の:

    db.sample.aggregate([
    
        // Store unique documents grouped by the "name"
        {$group: { 
            _id: "$name",
            comp: {
                $addToSet: { 
                    name:"$name",
                    type: "$type" 
                }
            } 
        }},
    
        // Unwind the "set" results
        {$unwind: "$comp"},
    
        // Push the results back to get the unique count
        // *note* you could not have done this with alongside $addtoSet
        {$group: {
            _id: "$_id",
            comp: {
                $push: { 
                    name: "$comp.name",
                    type: "$comp.type" 
                }
            },
            count: {$sum: 1} 
        }},
    
        // Match only what was counted once
        {$match: {count: 1}},
    
        // Unwind the array
        {$unwind: "$comp"},
    
        // Clean up to "name" and "type" only
        {$project: { _id: 0, name: "$comp.name", type: "$comp.type"}}
    
    ])
    

    この操作により、次の結果が得られます:

    { "name" : "f", "type" : "e" }
    { "name" : "z", "type" : "z" }
    

    ここで、SQLクエリと同じ結果を取得するために、それらの結果を取得して別のクエリに送ります。

    db.sample.find({$nor: [{ name: "f", type: "e"},{ name: "z", type: "z"}] })
    

    最終的なマッチング結果として到着するもの:

    { "name" : "a", "type" : "b" }
    { "name" : "a", "type" : "c" }
    { "name" : "b", "type" : "c" }
    { "name" : "b", "type" : "a" }
    { "name" : "a", "type" : "b" }
    { "name" : "b", "type" : "c" }
    

    したがって、これは機能しますが、これを非現実的にする可能性がある1つのことは、比較されるドキュメントの数です。 が非常に大きいため、これらの結果を配列に圧縮する際の作業限界に達しました。

    また、ネガティブの使用にも少し苦労します コレクションのスキャンを強制する最終検索操作で。しかし、公平を期すために、同じネガティブを使用するSQLクエリについても同じことが言えます。 前提。

    編集

    もちろん、私が言及しなかったのは、結果セットが逆になり、もっと一致している場合です。 結果として集計から除外されたアイテムが生成され、ロジックを逆にして必要なキーを取得します。 $ matchを次のように変更するだけです:

    {$match: {$gt: 1}}
    

    そしてそれが結果になります。実際の文書ではないかもしれませんが、それは結果です。したがって、否定的なケースに一致させるために別のクエリは必要ありません。

    そして、最終的にこれは私のせいでした。なぜなら、私は慣用的な翻訳に集中していて、読んでいないからです。 質問の最後の行、実行する 1つを探していたと言います ドキュメント。

    もちろん、現在 その結果のサイズが16MBより大きい場合は、スタックします。少なくとも2.6まで リリース。集計操作の結果はカーソル 、したがって、 .find()のように繰り返すことができます 。

    2.6でも導入 $ size ドキュメント内の配列のサイズを見つけるために使用される演算子。したがって、これは2番目の $ unwindを削除するのに役立ちます および$group セットの長さを取得するために使用されます。これにより、クエリがより高速な形式に変更されます:

    db.sample.aggregate([
        {$group: { 
            _id: "$name",
            comp: {
                $addToSet: { 
                    name:"$name",
                    type: "$type"
                }
            } 
        }},
        {$project: { 
            comp: 1,
            count: {$size: "$comp"} 
        }},
        {$match: {count: {$gt: 1}}},
        {$unwind: "$comp"},
        {$project: { _id: 0, name: "$comp.name", type: "$comp.type"}}
    ])
    

    また、MongoDB 2.6.0-rc0は、個人的な使用、または開発/テストのためだけにこれを行っている場合に現在利用可能です。

    この話の教訓。はい、できます やる、でも 本当に 欲しいまたは必要 そのようにするために?それならおそらくそうではなく、特定のビジネスケースについて別の質問をした場合、別の答えが得られる可能性があります。しかし、繰り返しになりますが、これはあなたが望むものにぴったりかもしれません。

    SQLの結果を見ると、誤って重複することに注意してください。 DISTINCT を使用しなかった場合、他の利用可能なタイプオプションによるいくつかの項目 それらの値または本質的に別のグループ化。しかし、それはMongoDBを使用したこのプロセスによって生成された結果です。

    アレクサンダーの場合

    これは、現在の2.4.xバージョンからのシェル内のアグリゲートの出力です:

    {
        "result" : [
                {
                        "name" : "f",
                        "type" : "e"
                },
                {
                        "name" : "z",
                        "type" : "z"
                }
        ],
        "ok" : 1
    }
    

    したがって、次のように、2番目の検索で$nor条件の引数として渡される変数を取得するためにこれを行います。

    var cond = db.sample.aggregate([ .....
    
    db.sample.find({$nor: cond.result })
    

    そして、同じ結果が得られるはずです。それ以外の場合は、ドライバーに相談してください。



    1. Debian10にCouchDBをインストールする方法

    2. 複数のコレクションでトランザクションを実行中にMongoDBAtlasエラーが発生しました(コード8000)

    3. mongoengineのoperatorallとicontainsの使用法を組み合わせる方法

    4. Mlabに保存されているオーディオの取得-バイナリファイル-