2016-07-07 99 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場tiebreak爲真只顯示tiebreak爲false的場數。請不要考慮它的邏輯,它是爲了讓用戶完全自由而設計的。

{ 
    $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個sql視圖。

我需要/想要嘗試重寫以前的獨特聚合只有一個。這可以實現嗎?

它是強制性的,以保持聚合的&乙中設置的所有限制,而不丟失數據的任何控制和而不泄漏和數據,這不是在查詢甲可用或B.

具體而言,在匹配只有當他們至少有一套以搶七結束時才能看到溫網。玩家1字段可以看到。如果沒有以tiebreak結尾並且以其他方式隱藏,則必須隱藏單個套。 如果需要,可以接受但不可取的是根本不會看到player1。

相反,只有當他們至少有一組沒有平局休息時才能看到羅蘭加洛斯的比賽。玩家1場必須隱藏。如果他們以tiebreak結束並且以其他方式隱藏,則必須看到單個組。

同樣,目的是聯合兩個聚合,同時保持兩個聚合強加的限制。

MongoDB是3.5版本,如果需要可以升級到unstable版本。

+0

在文本過濾器中使用正則表達式是額外的。以績效爲導向的戰略是一個加,但不是強制性的。 – Manuele

+0

在我看來,你是從一個集合中提取數據,所以要獲得這兩種類型的數據試試$或。 UNION通常從具有相似列的不同表中抽取。 – Tiramisu

+0

是的,我從同一個集合拉...但不幸的是,點不在$匹配階段(使用$或...),但$項目階段,這似乎是不可能/太難我...謝謝無論如何! – Manuele

回答

0

這裏是我的問題,兩分錢:
如果你想避免空集時

  • 一個 「溫布爾登」 DOC具有所有true tibreaks,
  • 或「羅蘭加洛斯「已有全部false搶七破

你可以重塑查詢:

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

,並使用它:

+0

很難說哪一個是正確的行爲,因爲這只是一個測試。這一點是模仿SQL UNION。由於「Aggregation ALFA/BETA」會返回空集,我*認爲*我的查詢仍然是最正確的,但是您的註釋指向的不是正確的註釋。 這將是很好的基準兩種不同的方法。我認爲更多的階段=更多的時間,但它也可能是一個* hard *投影可能會消耗比匹配/展開/匹配列表更多的時間...將調查... – Manuele

+0

我不會將您的答案標記爲請在前面的評論中糾正原因,但這無疑是一種有效的方法。 – Manuele