虽然我坚持认为您提出问题的方式实际上与您遇到的特定问题无关,但我会以某种方式解释 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操作的逻辑。所以另一种说法是“哪些文档给出了“名称”键do有超过one键“type”中的可能值。
鉴于此,采用 mongo 方法,我们可以查询以下项目do not符合给定的条件。所以有效地reverse结果:
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" }
所以这会起作用,但是可能使这不切实际的一件事是文档的数量compared非常大,我们在将这些结果压缩为数组时遇到了工作限制。
它也因使用而受到一些影响negative在最终的查找操作中,这将强制扫描集合。但平心而论,使用相同的 SQL 查询也可以这样说negative前提。
Edit
当然我没有提到的是,如果结果集相反并且你正在匹配more结果是从聚合中排除的项目,然后只需反转逻辑即可获取所需的键。只需更改 $match 如下:
{$match: {$gt: 1}}
这就是结果,也许不是实际的文件,但它是一个结果。因此,您不需要另一个查询来匹配否定案例。
而且,归根结底,这是我的错,因为我太专注于惯用翻译,而没有做到这一点。read你问题的最后一行,去哪里do说你正在寻找one文档。
当然,现在如果结果大小大于 16MB,那么您就会陷入困境。至少直到2.6发布,其中聚合操作的结果是cursor,所以你可以像这样迭代.find()
.
还介绍了2.6 is the $size运算符用于查找文档中数组的大小。所以这将有助于删除第二个$unwind
and $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。
故事的道德启示。是的,就是你can do it, But do you really想要或need这样做吗?那么可能不会,如果您针对特定业务案例提出不同的问题,您可能会得到不同的答案。但话又说回来,这可能完全适合你想要的。
Note
值得一提的是,当你查看 SQL 的结果时,它会错误地复制如果您没有使用其他可用类型选项,则有几个项目DISTINCT
对于这些值或本质上是另一个分组。但这是使用 MongoDB 的过程产生的结果。
为了亚历山大
这是当前 2.4.x 版本中 shell 中聚合的输出:
{
"result" : [
{
"name" : "f",
"type" : "e"
},
{
"name" : "z",
"type" : "z"
}
],
"ok" : 1
}
因此,这样做可以让 var 作为参数传递给第二个查找中的 $nor 条件,如下所示:
var cond = db.sample.aggregate([ .....
db.sample.find({$nor: cond.result })
您应该得到相同的结果。否则请咨询您的司机。