如何使用MongoDB选择子文档

11

我有一个包含子文档 tags 的集合:

Collection News :
   title (string)
   tags: [tag1, tag2...]
我想选择所有以某种模式开头的标签,但只返回匹配的标签。我已经使用了正则表达式,但它返回包含匹配标签的所有新闻。以下是查询语句:
db.news.find( {"tags":/^proga/i}, ["tags"] ).sort( {"tags":1} ).
    limit( 0 ).skip( 0 )

我的问题是:如何检索与模式匹配的所有标签(仅限标签)?(最终目标是创建一个自动完成字段)

我也尝试过使用distinct,但是我没有找到一种通过find进行去重的方法,它总是将所有标签都返回给我:(

谢谢您的时间

2个回答

13

有点晚了,但希望能帮助其他正在寻找解决方案的人。我已经找到了一种使用聚合框架完成此操作的方法,并将 $project 和 $unwind 与 $match 相结合,通过链接它们在一起。我是用 PHP 实现的,但你应该可以理解:

    $ops = array(
        array('$match' => array(
                'collectionColumn' => 'value',
            )
        ),
        array('$project' => array(
                'collection.subcollection' => 1
            )
        ),
        array('$unwind' => '$subCollection'),
        array('$match' => array(
                subCollection.subColumn => 'subColumnValue'
            )
        )
    );

首先的match和project只是用来过滤以使其更快,然后在子集合上进行展开,逐个输出每个子集合项,然后可以使用最终的match进行过滤。

希望能够帮到您。

更新(来自Ryan Wheale):

然后可以使用$group将数据重新组合成原始结构。 这就像有一个返回多个子文档的$elemMatch:

array('$group' => array(
        '_id' => '$_id',
        'subcollection' => array(
            '$push' => '$subcollection'
        )
    )
);

我将这段代码从Node翻译成PHP,所以我还没有在PHP中测试过。如果有人想要Node版本,请在下面留言,我会提供。


1
老兄,真是天才。我无法描述当我找到这个时的灵光一现。你也可以把这些项 $group 起来,还原它们的原始结构。我需要一个相当于 $elemMatch 投影的东西,它可以返回多个结果。谢谢! - Ryan Wheale

10

嵌入式文档不是集合。看看您的查询:db.news.find将返回来自news集合的文档。 tags不是一个集合,也无法进行过滤。

有一个关于“虚拟集合功能”的特性请求(SERVER-142),但不要指望很快就能看到它,因为它“计划中但未安排时间”。

您可以在客户端进行过滤,或将标签移动到单独的集合中。通过仅检索子集字段 - 仅tags字段 - 这应该是相当快速的。

提示:您的正则表达式使用了/i标志,这使得无法使用索引。您的数据库字符串应该进行大小写归一化(例如全部大写)


谢谢你的回答,我会尝试创建另一个集合“tags”,其中包含所有我的标签,并在此集合上进行过滤(但不确定它是否符合NOSQL方式)。 - Mush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接