MongoDB中的数组交

MongoDB中的数组交,mongodb,mongodb-.net-driver,mongodb-query,Mongodb,Mongodb .net Driver,Mongodb Query,好的,这里有两件事……我有两个集合:test和test1。两个集合中的文档都有一个数组字段(分别是tags和tags1),其中包含一些标记。我需要找到这些标记的交集,如果单个标记匹配,还需要从collection test1获取整个文档 >db.test.find(); { “_id”:ObjectId(“5166c19b32d001b79b32c72a”), “标签”:[ “a”, “b”, “c” ] } >db.test1.find(); { “_id”:ObjectI

好的,这里有两件事……我有两个集合:test和test1。两个集合中的文档都有一个数组字段(分别是tags和tags1),其中包含一些标记。我需要找到这些标记的交集,如果单个标记匹配,还需要从collection test1获取整个文档

>db.test.find();
{
“_id”:ObjectId(“5166c19b32d001b79b32c72a”),
“标签”:[
“a”,
“b”,
“c”
]
}          
>db.test1.find();
{
“_id”:ObjectId(“5166c1c532d001b79b32c72b”),
“标记1”:[
“a”,
“b”,
“x”,
“y”
]
}
>db.test.find().forEach(函数(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”]} 但这是我需要的一部分。我也需要十字路口。所以我试了一下:

但它只返回“a”,而“a”和“b”都在tags1中。位置运算符是否仅返回第一个匹配?另外,在中使用
$并不能准确地给我一个交集。我如何才能得到一个交集(应该返回“a”和“b”),而不管哪个数组与另一个数组进行比较。

现在假设有一个接线员可以做到这一点。。

我的要求是,我需要整个tags1数组加上这个交集,在同一个查询中,如下所示:

但这是一个无效的json。是否可以重命名密钥,或者仅通过聚合框架(以及跨不同集合)重命名密钥?我用
$in
尝试了上述查询。但它的行为似乎完全忽略了标签1的投影

PS:我在Test1中至少有10K DOC,(P)如果你想实时处理这个问题,你应该考虑远离服务器端JavaScript,它只运行一个线程,应该相当慢(单线程)(这对于V2.4不再适用)。 位置运算符仅返回第一个匹配/当前值。在不了解内部实现的情况下,从性能角度来看,如果文档已评估为匹配,则寻找进一步的匹配条件甚至没有意义。因此,我怀疑您是否可以这样做

我不知道你是否需要笛卡尔产品来搜索,但是我会考虑把你的几个测试文档标签加入一个,然后在Test1上搜索它,返回所有匹配的文档。在你的本地机器上你可以有多个线程来生成你的文档的交集。

根据test1和test collection更改的频率,您在执行此查询时可能会预先计算此信息。这将允许您轻松地对包含交叉点信息的字段进行查询


该文档无效,因为您有两个字段名tags1

Mongo没有检索数组交叉点的任何固有功能。如果确实需要使用特殊查询,请在客户端获取交叉点


另一方面,考虑使用Map Reduce并将它的输出存储为一个集合。您可以在FialAllia节中添加返回的对象以添加交叉标记。CRON MR每隔几秒钟运行一次。您可以从客户端接收到永久性集合的好处。

在较新版本中,您可以使用。要做到这一点

db.test.aggregate(
    {
        $match: {
            tags1: {
                $in: doc.tags
            }
        }
    },
    {
        $project: {
            tags1: 1,
            intersection: {
                $setIntersection: [doc.tags, "$tags1"]
            }
        }
    }
);

如您所见,
match
部分与初始的
find()完全相同
query.
project
部分生成结果字段。在本例中,它从匹配的文档中选择
tags1
,并从输入和匹配的文档中创建
intersection

对第一个问题“db.test1.find({tags1:{$In:doc.tags}”)进行评论将返回一个游标。要打印到屏幕,您应该在第二个查找中附加以下内容:.forEach(函数(doc){print(tojson(doc));}谢谢@JamesWahlin!我知道这很愚蠢:P你的快速评论让我至少可以进一步找到解决方案。为什么服务器端JS相关?他在尝试中没有做任何服务器端JS-shell在客户端机器上本地运行JS。是的,你是对的,javascript是在本地执行的。我在这里走错了方向.
> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a", "b" ] }
> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1":1, "tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1": [ "a", "b", "x", "y" ],
"tags1" : [ "a", "b" ] }
db.test.aggregate(
    {
        $match: {
            tags1: {
                $in: doc.tags
            }
        }
    },
    {
        $project: {
            tags1: 1,
            intersection: {
                $setIntersection: [doc.tags, "$tags1"]
            }
        }
    }
);