MongoDB:如何在同一数据库中搜索多个集合并返回混合结果集?
我有一个单页面应用程序,它使用我在Node.js上运行并使用MongoDB进行数据存储的JavasScript编写的API。API公开了几种不同的内容类型,每种内容类型都存储在我的MongoDB数据库中的一个单独集合中。我的单页面应用程序有一个搜索栏,其中包含一个用于选择内容类型的下拉列表(每个内容类型对应于我的MongoDB数据库中的一个不同集合)和一个输入栏,用于指定将应用的搜索查询。
我想做的是:在我的下拉列表中添加一个名为"All"的选项,选择此选项后,我的API将返回最近创建的五个文档,而不考虑包含这些文档的集合。
因此,作为示例,我可能有以下集合:
- 汽车
- 飞机
- 船
- 自行车
我想在我的API中编写JavaScript,以返回其中最新的5个。因此,如果用户搜索"G",我生成的JSON响应可能包含每个集合中的几个文档,如下所示:
[
{
"_id": "123",
"name": "Golf,
"collection: "Automobile",
"createdAt": "2014-06-20T01:45:00.0000Z"
},
{
"_id": "234",
"name": Gulfstream",
"collection": "Airplane",
"createdAt": "2014-06-19T01:45:00.0000Z"
},
{
"_id": "345",
"name": "Glastron",
"collection": "Boat",
"createdAt": "2014-06-18T01:45:00.0000Z"
},
{
"_id": "456",
"name": "Gary Fisher",
"collection" "Bicycle",
"createdAt": "2014-06-17T01:45:00.0000Z"
}
{
"_id": "567",
"name": "Grand Prix",
"collection": "Automobile",
"createdAt": "2014-06-16T01:45:00.0000Z"
}
]
问题:在Mongo中是否可以跨多个集合进行搜索,如果可以,我如何执行此操作?
请注意:
- 这与尝试在Mongo中执行联接是一个非常不同的问题--或者至少可以是这样。(参见:MongoDB - Search on multiple collections。我不会像在联接中那样尝试关联来自不同集合的文档。(例如,不能说Boves集合中的文档包含有关Automobiles集合中文档的详细信息。)
- 似乎有一个糟糕的解决方案,需要为每个集合运行查询(即,查询五辆汽车、五架飞机、五艘船和五辆自行车;将结果合并到一个数组中,按createdAt排序,然后将前五个从数组前面拼接起来)。参见:Meteor.js - ways to do user search over multiple collections。但是,如果可能的话,我希望避免这种情况,因为(I)这将使查询效率降低5倍;(Ii)这将使分页非常困难。
- 我使用Sails.js作为我的框架(因此,Waterline作为我的ORM)。因此,即使这在Mongo层是不可能的,我推测它可能已经在ORM层实现了。是这样吗?如果是这样,我将如何使用它?
解决方案
虽然John Petrone的评论非常有帮助(因为它指出我在Mongo遇到了一个限制),但我确实想整理一个可能的解决方案的全面列表:
- 为每个集合运行查询(即,查询五辆汽车、五架飞机、五艘船和五辆自行车;将结果合并到一个数组中,按createdAt排序,然后将前五个从数组前面拼接起来)。(请参阅上面问题中有关此解决方案的更多详细信息)。
- 根据上面John Petrone的注释,将所有这些类型的对象存储在同一集合中。 通过仅存储生成搜索结果所需的每个文档的数据的副本来去规格化数据;所有这样的副本,无论它们的源文档存储在哪个集合中,都可以保存在一个集合中(例如,称为SearchResults),并且在My SPA中的搜索可以向查询该集合中的文档的API端点发出请求。这是John Petrone提出的解决方案(在上面的注释中)的改编,该解决方案考虑到了我使用过的JavaScript/Mongo Orm(即Waterline和Mongoose)的实际限制,如果您想要在同一集合中存储使用不同模型构建的文档,这一切都会让您的生活变得非常糟糕。缺点:需要额外的创建、更新和删除查询;需要存储更多数据;必须使SearchResult数据与源文档保持同步。优点:高效的读取查询;轻松兼容JavaScript/Mongo Orms。
相关文章