2016-07-07 16 views
0

MongoDBでSQLの動作を複製する方法について、いくつかの助言や助言が必要です。MongoDb集約(SQL UNIONスタイル)

{ 
    "_id" : ObjectId("577ebc0660084921141a7857"), 
    "tournament" : "Wimbledon", 
    "player1" : "Agassi", 
    "player2" : "Lendl", 
    "sets" : [{ 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc3560084921141a7858"), 
    "tournament" : "Wimbledon", 
    "player1" : "Ivanisevic", 
    "player2" : "McEnroe", 
    "sets" : [{ 
     "score1" : 4, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 3, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc7560084921141a7859"), 
    "tournament" : "Roland Garros", 
    "player1" : "Navratilova", 
    "player2" : "Graf", 
    "sets" : [{ 
     "score1" : 5, 
     "score2" : 7, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 3, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 7, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 5, 
     "tiebreak" : false 
    }] 
} 

そして、これら二つの異なる集計:具体的には、このコレクションを与え

1)集約ALFA:この集約は、すべての一致を見つけるために設計されたという意味で、意図的に奇妙です少なくとも1回のタイブレークは真ですしかしは、タイブレークが偽であるセットを表示します。それの論理を考慮しないでください、それはユーザーに完全な自由を許すように作られています。

{ 
    $match: { 
     "tournament": "Wimbledon", 
     "sets.tiebreak": true 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "player1": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", false] 
       } 
      } 
     } 
    } 
} 

2)集約BETA:この集約は、少なくとも1タイブレークが偽ですが、タイブレークが真であるところはセットのみを表示し、すべての一致を検索するように設計されているという意味で、意図的に変だ 。それの論理を考慮しないでください、それはユーザーに完全な自由を許すように作られています。 player1が結果から隠されています。

{ 
    $match: { 
     "tournament": "Roland Garros", 
     "sets.tiebreak": false 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", true] 
       } 
      } 
     } 
    } 
} 

は現在、これらの2件の集計の目的は、ユーザーがこれらの2つのクエリがユーザーに表示されているすべての文書(および詳細)を区切るという意味で、見ることができるデータベースのどの部分区切るためにあるとします。これは、ユーザーがアクセス権を持つ2つのSQLビューに似ています。

以前の個別の集計を1つのみで書き直す必要があります。これは達成できますか?

特異的に一致するクエリAまたはB

で利用できなかったことをデータ上の任意のコントロールを失うことなく、かつ漏洩することなく、集合体A & Bに設定されたすべての制限を維持するために必須であり、データウィンブルドンは、少なくとも1つのセットがタイブレークで終わった場合にのみ見ることができます。 Player1フィールドが表示されます。単一のセットはタイブレークで終わらず、それ以外の場合は隠されていなければ非表示にする必要があります。 必要に応じて、player1がまったく表示されないようにすることは可能ですが、好ましくはありません。

逆に、Roland Garrosでのマッチは、タイブレイクなしで終了したセットが少なくとも1つしかない場合にのみ表示されます。 Player1フィールドは非表示にする必要があります。単一のセットはタイブレークで終了し、それ以外の場合は隠されている必要があります。

再び、目的は、2つの集計によって課される制限を維持しながら、2つの集計を結合することです。

MongoDBはバージョン3.5です。必要に応じて不安定なリリースにアップグレードできます。

+0

テキストフィルタで正規表現を使用することは余分になります。パフォーマンス指向の戦略はプラスですが、必須ではありません。 – Manuele

+0

私はあなたが1つのコレクションからデータを取り出すように思われるので、両方のタイプのデータを$またはを試してみてください。通常、UNIONは類似した列を持つ異なる表から引き出します。 – Tiramisu

+0

はい、私は同じコレクションから引っ張っています...しかし、残念ながら、ポイントは$マッチステージ($や...を使用しています)ではなく、私にとっては不可能/難しそうな$プロジェクトステージです...ありがとういずれかの方法! – Manuele

答えて

0

ここでの問題のために私の2セントです:

  • "ウィンブルドン" DOCはすべてtrue tibreaks、
  • または「ローランギャロスを持っているときに、空集合を避けたい場合
    "はすべてfalseタイブレーク

クエリ作り直すことがあります。

... 
{ 
    $and: [{ 
    "sets.tiebreak": true, 
    }, { 
    "sets.tiebreak": false 
    }], 
    $or: [{ 
    "tournament": "Wimbledon" 
    }, { 
    "tournament": "Roland Garros" 
    }] 
} 
... 

をし、それを使用中:

+0

これは単なるテストだったので、どちらが正しい動作であるかを知るのは難しいです。この点は、SQL UNIONを模倣することでした。 "集計ALFA /ベータ"は空のセットを返すので、私のクエリは依然として最も正しいと思いますが、あなたの注釈は正しい注釈以上のものを指しています。 2つの異なるアプローチをベンチマークするのがよいでしょう。私はより多くのステージ=より多くの時間がかかると考えていますが、ハード・プロジェクションがマッチ/アンワインド/マッチのリストよりももっと時間を消費するかもしれません...調査する... – Manuele

+0

私はあなたの答えを前のコメントの理由で正しいものを修正してください。しかし確かに有効なアプローチです。 – Manuele