我是使用MongoDB的新手,我不知道如何解决下一个问题:
我有这样的文件集合:
{
"URL": "www.stackoverflow.com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
首先,我想要所有包含列表中所有标签的Url。 我通过查询来解决这个问题:
db.links.find( { "Tags.Name" : { $all: ["question","answers"] } } );
但是这个查询会返回整个正确的文档,只提供正确的文档,只包含我要求的标记。
我正在寻找的结果是:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5}]
}
而不是:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}]
}
因为我只要求标签[“问题”,“答案”]。
我考虑过使用MapReduce或解析结果集,但我不知道它是否是解决问题的正确方法。也许有一个内置函数可以更有效地解决它。
谢谢!
答案 0 :(得分:18)
您可以使用MongoDB
的聚合框架。
如果您的收藏中有一份文档,请
{
"URL": "www.stackoverflow.com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
并且您希望过滤数组的某些元素,您可以使用聚合样本;
db.sof_table.aggregate
([
{$unwind:'$TAGS'},
{$match:{'TAGS.NAME':{$in:['answer','question']}}},
{$group:{_id:'$URL',TAGS:{$push:'$TAGS'}}}
])
这将导致结果;
{
"result" : [
{
"_id" : "www.stackoverflow.com",
"TAGS" : [
{
"NAME" : "question",
"VOTES" : 3
},
{
"NAME" : "answer",
"VOTES" : 5
}
]
}
],
"ok" : 1
}
作为您的预期结果。
答案 1 :(得分:8)
一般来说,MongoDB上的任何find()
操作都会返回与查询匹配的所有文档,并且会完整地检索所有文档。如果您只想要文档的特定部分,那么您必须在客户端进行该处理。
这是文档数据库和SQL数据库之间的根本区别。通常在文档数据库中,查询返回与其匹配的所有文档,而在SQL数据库中,您可以选择仅返回表的某些部分。当然,除非你说你做了MapReduce,但对你的用例来说这似乎有些过分。
不要阻止你使用MongoDB,但是你工作的任何项目都要考虑NoSQL数据库是否真的符合要求(它们是否满足了SQL不能满足的要求),或者你是否仍然更好地使用传统的SQL数据库。 / p>
答案 2 :(得分:3)
可以在返回的文档中禁止键和数组元素,但不能以您想要的方式。
在您的示例中,您可以使用以下查询来抑制URL密钥,该查询使用第二个参数find():
db.links.find({"TAGS.NAME" : {$all : ["question","answer"]}}, {"URL" : 0})
但是,我不相信可以使用find()基于使用$ all指定的数组成员来抑制服务器端数组的各个成员。
您可以使用$ slice仅返回数组的某些成员,但它是基于位置的。例如,
{$slice : [1, 2]}
跳过数组的第一个元素并返回到接下来的两个元素。
答案 3 :(得分:-1)
谢谢罗伯特。我已经意识到我正在寻找的功能目前还没有实现。这是issue的链接。我希望MongoDB cominuty能在短时间内实现它。谢谢!
答案 4 :(得分:-1)
这可能会对你有帮助。
$ elemMatch投影运算符采用显式条件参数。这允许您根据不在查询中的条件进行投影,或者是否需要基于数组嵌入文档中的多个字段进行投影。**
https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/