这里有几件事情需要处理。我有两个集合:test和test1。这两个集合中的文档都有一个数组字段(分别为tags和tags1),其中包含一些标签。我需要找出这些标签的交集,并且如果存在单个标签匹配,就从test1集合中获取整个文档。
> db.test.find();
{
"_id" : ObjectId("5166c19b32d001b79b32c72a"),
"tags" : [
"a",
"b",
"c"
]
}
> db.test1.find();
{
"_id" : ObjectId("5166c1c532d001b79b32c72b"),
"tags1" : [
"a",
"b",
"x",
"y"
]
}
> db.test.find().forEach(function(doc){db.test1.find({tags1:{$in:doc.tags}})});
令人惊讶的是,这并没有返回任何内容。然而当我尝试使用单个文档时,它可以工作:
> var doc = db.test.findOne();
> db.test1.find({tags1:{$in:doc.tags}});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a", "b", "x", "y" ] }
但这只是我需要的一部分。我还需要交集。所以我尝试了这个:
> db.test1.find({tags1:{$in:doc.tags}},{"tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a" ] }
但是它只返回了"a",而"a"和"b"都在标签中。位置操作符只返回第一个匹配项吗?此外,使用
$in
无法精确给出交集。我应该如何获得交集(应该返回"a"和"b"),而不考虑哪个数组与另一个进行比较。现在假设有一个可以做到这一点的操作符..> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a", "b" ] }
我的要求是,在同一查询中获取整个tags1数组及此交集,如下所示:
> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1":1, "tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1": [ "a", "b", "x", "y" ],
"tags1" : [ "a", "b" ] }
但是这是一个无效的 JSON。是否可以重命名键名,或者只能通过聚合框架实现(跨不同集合)?我尝试了上面的查询和
$in
。但它的行为就像完全忽略了 "tags:1"
投影一样。PS:我将在test1中有至少10k个文档,在test中只有很少的文档(<10)。而且这个查询是实时的,所以我想避免使用MapReduce :)
谢谢任何帮助!