我具有以下结构(无法更改,这是我必须使用的结构):
{
"_id" : ObjectId("abc123"),
"notreallyusedfields" : "dontcare",
"data" : [
{
"value" : "value1",
"otherSomtimesInterestingFields": 1
"type" : ObjectId("asd123=type1"),
},
{
"value" : "value2",
"otherSometimesInterestingFields": 1
"type" : ObjectId("asd1234=type2"),
},
many others
]
}
因此,基本上,架构的字段位于数组内部,并且可以基于1个数组元素(1个架构字段,其值为数组中的1个元素)中的type字段进行标识。对我来说,这很奇怪,但是我是NoSQL的新手,所以这可能没问题。 (同样对于不同的数据,某些字段可能会丢失,并且不能保证数据数组中的元素顺序)
也许这样更容易理解: 表a:type1列| type2列|等等(这些都存储在上面的数组中)
我的问题是:如何根据条件选择多个字段?我的意思是(在SQL中):SELECT * FROM table WHERE type1 = value1 AND type2 = value2
我可以这样选择1:
db.a.find( {"data.type":ObjectId("asd1234=type2"), "data.value":value2}).pretty()
但是我不知道该如何包含type1 = value1甚至更多条件。而且我认为这甚至不好,因为它可以匹配数组中的任何data.value字段,因此这并不意味着类型为type2的值必须为value2。
您将如何解决?
我当时想对1个条件进行1个查询,然后根据结果进行另一个查询。因此,类似聚合的管道,但是正如我所见,$ match不能在聚合中多次使用。我猜有一种管道这些命令的方法,但这很丑陋。 我想念什么?还是由于数据的结构,我不得不做这些奇怪的多重查询?
我也看过$ filter,但是那里的条件也适用于数组的任何元素。 (或者我做错了)
谢谢!
抱歉,如果我不够清楚!请询问,我可以详细说明。
(基本上我要基于此结构(Retrieve only the queried element in an object array in MongoDB collection来做的是这样的:如果形状为正方形,则过滤为蓝色,如果形状为圆形,则过滤为红色,===如果类型是type1的值必须是value1,如果type是type2的值必须是value2)
答案 0 :(得分:1)
这可以像这样完成:
db.document.find( { $and: [
{ type:ObjectId('abc') },
{ data: { $elemMatch: { type: a, value: DBRef(...)}}},
{ data: { $elemMatch: { type: b, value: "string"}}}
] } ).pretty()
因此,您可以使用$添加任意数量的“条件”,然后可以指定一个元素必须具有类型a和值b,另一个元素必须具有类型b和值c ...
如果只想投影匹配的元素,则将聚合与过滤器一起使用:
db.document.aggregate([
{$match: { $and: [
{ type:ObjectId('a') },
{ data: { $elemMatch: { Type: ObjectId("b"), value: DBRef(...)}}},
{ data: { $elemMatch: { Type: ObjectId("c"), value: "abc"}}}
] }
},
{$project: {
metadata: {
$filter: {
input: "$data",
as: "data",
cond: { $or: [
{$eq: [ "$$data.Type", ObjectId("a") ] },
{$eq: [ "$$data.Type", ObjectId("b") ] }]}
}
}
}
}
]).pretty()
这非常丑陋,因此,如果有更好的方法,请发布!谢谢!
答案 1 :(得分:0)
如果您需要检索具有匹配的数组元素的文档 多个条件,则必须使用$elemMatch query operator。
db.collection.find({
data: {
$elemMatch: {
type: "type1",
value: "value1"
}
}
})
这将输出元素匹配的整个文档。
要仅输出数组中的第一个匹配元素,可以将其与$elemMatch projection operator组合。
db.collection.find({
data: {
$elemMatch: {
type: "type1",
value: "value1"
}
}
},
{
data: {
$elemMatch: {
type: "type1",
value: "value1"
}
}
})
警告,不要忘记将所需的所有其他字段投影到数据数组之外。
如果需要输出数组中所有匹配的元素,则必须在聚合$ project阶段使用$filter,如下所示:
db.collection.aggregate([
{
$project: {
data: {
$filter: {
input: "$data",
as: "data",
cond: {
$and: [
{
$eq: [
"$$data.type",
"type1"
]
},
{
$eq: [
"$$data.value",
"value1"
]
}
]
}
}
}
}
}
])