我需要一些关于如何在MongoDB中复制一些SQL行为的帮助/建议。具体来说,给定此集合:
{
"_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 个抢七为假的所有匹配项,但只显示平局为真的集合。请不要考虑它的逻辑,它的设计是为了让用户完全自由。请注意,玩家 1 在结果中是隐藏的。
{
$match: {
"tournament": "Roland Garros",
"sets.tiebreak": false
}
},
{
$project: {
"tournament": 1,
"sets": {
$filter: {
input: "$sets",
as: "set",
cond: {
$eq: ["$$set.tiebreak", true]
}
}
}
}
}
现在假设这两个聚合的目的是界定用户可以看到的数据库的哪个部分,从某种意义上说,这两个查询界定了用户可见的所有文档(和详细信息)。这类似于用户有权访问的 2 个 sql 视图。
我需要/想尝试仅在一个聚合中重写以前的不同聚合。这能实现吗?
必须保留在聚合 A 和 B 中设置的所有限制,而不会失去对数据的任何控制,也不会泄漏和查询 A 或 B 中不可用的数据。
具体来说,温布尔登的比赛只有在至少一盘以抢七结束的情况下才能看到。可以看到玩家 1 字段。如果单盘没有以抢七结束,则必须隐藏,否则必须隐藏。如果需要,完全看不到 player1 是可以接受的,但不可取。
相反,罗兰加洛斯的比赛只有在至少有一盘没有平局的情况下才能看到。玩家 1 字段必须隐藏。如果单盘以抢七结束,则必须看到它们,否则隐藏。
同样,目的是联合两个聚合,同时保持两个聚合施加的限制。
MongoDB是3.5版本,如果需要,可以升级到不稳定版本。
这是我对这个问题的两分钱:
如果您希望在以下情况下避免空集
- 一个"温布尔登"文档有
true
所有的蒂瓦斯, - 或"罗兰加洛斯"拥有所有
false
决胜局
您可以重塑查询:
...
{
$and: [{
"sets.tiebreak": true,
}, {
"sets.tiebreak": false
}],
$or: [{
"tournament": "Wimbledon"
}, {
"tournament": "Roland Garros"
}]
}
...
并将其用于:
- 聚合管道 http://pastebin.com/cM6mNsuC
- mapReduce(如果性能不是一个大问题..) http://pastebin.com/MShihSQL