所以我有这个查询
db.collection.find($or:[{data_id:123},{data_id:345},{data_id:443}]);
如何调整它以仅返回$或的每个部分中的一个。 I.E类似于SQL:
SELECT DISTINCT data_id, [...] WHERE data_id='123' OR data_id='345'...
答案 0 :(得分:3)
您的问题需要考虑您所拥有的文件,因为“不同”可能意味着一些不同的事情。请考虑以下示例:
{
"tripId": 123,
"thisField": "this",
"thatField": "that"
},
{
"tripId": 123,
"thisField": "other",
"thatField": "then"
},
{
"tripId": 345,
"thisField": "other",
"thatField": "then"
},
{
"tripId": 345,
"thisField": "this",
"thatField": "that"
},
{
"tripId": 123,
"thisField": "this",
"thatField": "that"
},
{
"tripId": 789,
"thisField": "this",
"thatField": "that"
}
MongoDB有.distinct()
方法,该方法会为单个字段返回不同的值,但只有一个字段以及这些项只是作为这些字段值的数组返回。
对于其他任何你想要的.aggregate()
方法。这是聚合管道,它具有许多不同的功能,并且由于处理的“管道”特性,可以处理一些非常复杂的操作。
特别是在这里,您可能希望使用$group
管道阶段,以便根据键将值“组合”在一起。该“密钥”以_id
语句中的$group
密钥的形式表示。与SQL中的“SELECT”非常相似,具有“GROUP BY”或“DISTINCT”修饰符(在功能上大致相同),您需要指定结果中所有要包含的字段。
此外,任何未在语句的“GROUP BY”部分中指定的内容都必须经过某种“分组操作”才能选择要显示的字段值。为此,有多种"Group Accumulator Operators"可以对这些值采取行动:
在这种情况下使用$first
运算符的一个示例:
db.collection.aggregate([
{ "$match": {
"tripId": { "$in": [ 123,345 ] }
}},
{ "$group": {
"_id": "$tripId",
"thisField": { "$first": "$thisField" },
"thatField": { "$first": "$thatField" },
"total": { "$sum": 1 }
}}
])
给出了这个结果:
{ "_id" : 345, "thisField" : "other", "thatField" : "then", "total" : 2 }
{ "_id" : 123, "thisField" : "this", "thatField" : "that", "total" : 3 }
因此,通过添加$sum
运算符来计算相同的不同值的出现次数,这将选择在分组之外的累加器表达式中提到的指定字段中的值的“第一次”出现键。
在2.6以后的MongoDB版本中,您可以使用$$ROOT
表达式变量“快捷”命名您想要的所有字段。这是对文档中存在的“所有”字段的引用,表示当前使用它的状态。写入时间要短一些,但由于语法的原因,输出略有不同:
db.collection.aggregate([
{ "$match": {
"tripId": { "$in": [ 123,345 ] }
}},
{ "$group": {
"_id": "$tripId",
"doc": { "$first": "$$ROOT" },
"total": { "$sum": 1 }
}}
])
输出为:
{
"_id" : 345,
"doc" : {
"_id" : ObjectId("54feaf3839c29b9cd470bcbe"),
"tripId" : 345,
"thisField" : "other",
"thatField" : "then"
},
"total" : 2
}
{
"_id" : 123,
"doc" : {
"_id" : ObjectId("54feaf3839c29b9cd470bcbc"),
"tripId" : 123,
"thisField" : "this",
"thatField" : "that"
},
"total" : 3
}
这是大多数$group
聚合操作的一般情况,您可以在其中指定“键”并将其他字段置于某种“分组运算符”/“累加器”中。
另一种情况是,如果您正在寻找“所有”字段的“不同”出现,那么您可以将这些表示为组表达式的“键”的一部分,如下所示:
db.collection.aggregate([
{ "$match": {
"tripId": { "$in": [ 123,345 ] }
}},
{ "$group": {
"_id": {
"tripId": "$tripId",
"thisField": "$thisField",
"thatField": "$thatField"
},
"total": { "$sum": 1 }
}}
])
这给了我们这个输出:
{
"_id" : {
"tripId" : 345,
"thisField" : "this",
"thatField" : "that"
},
"total" : 1
}
{
"_id" : {
"tripId" : 345,
"thisField" : "other",
"thatField" : "then"
},
"total" : 1
}
{
"_id" : {
"tripId" : 123,
"thisField" : "other",
"thatField" : "then"
},
"total" : 1
}
{
"_id" : {
"tripId" : 123,
"thisField" : "this",
"thatField" : "that"
},
"total" : 2
}
总结果是4个文档,它们考虑作为“复合键”一部分提到的每个字段的“不同”值。它正确地说明了大多数这些组合发生了一次,除了一个实例出现两次且所有相同值的例子。
当然,$$ROOT
变量不适用于此处,因为“整个文档”包含每个文档的“唯一”_id
字段。您可以随时添加$project
阶段来过滤该字段,但是指定所需字段的条件相同:
db.collection.aggregate([
{ "$match": {
"tripId": { "$in": [ 123,345 ] }
}},
{ "$project": {
"_id": 0,
"tripId": 1,
"thisField": 1,
"thatField": 1
}},
{ "$group": {
"_id": "$$ROOT",
"total": { "$sum": 1 }
}}
])
这是一个介绍,其中包含您可以使用MongoDB以及特别是聚合框架以“不同”查询形式执行的操作的示例。文档中给出了各种其他常见的SQL to Aggregation mapping示例。
另一般情况是您在问题中使用$or
。正如您在此处的示例中所看到的,当您希望在相同字段的值上使用相同的“或”条件时,在查询中使用$in
运算符的更有效方式。这不是一个“查询文档”数组,而是将“可能的值”数组带到它在表达式中检查的公共字段中。它基本上是一个$or
条件,但在这种情况下用较短的形式表示。
答案 1 :(得分:0)
而不是 $或使用 $ in 查询,以满足您的目的。
db.collection.find({data_id:{$ in:[123,345,443]}});