MongoDB - 查询难题 - 文档参考或子文档

Posted

技术标签:

【中文标题】MongoDB - 查询难题 - 文档参考或子文档【英文标题】:MongoDB - Query conundrum - Document refs or subdocument 【发布时间】:2015-07-06 09:54:10 【问题描述】:

我在存储在 MongoDB 中的一些数据遇到了一些问题(注意:我使用 mongoose 作为 ODM)。我有两个架构:

mongoose.model('Buyer',
  credit: Number,
)

mongoose.model('Item',
  bid: Number,
  location:  type: [Number], index: '2d' 
)

Buyer/Item 将具有父/子关联,具有一对多的关系。我知道我可以将项目设置为嵌入到买方文档的子文档我可以创建两个单独的文档,其中对象 id 相互引用。

我面临的问题是我需要查询出价低于买方信用的项目,还需要查询位置靠近某个地理坐标的位置。。 p>

为了满足第一个标准,我似乎应该将 Items 作为子文档嵌入,以便我可以比较这两个数字。但是,为了使用 geoNear 查询比较位置,似乎最好将文档分开,否则,我无法对每个子文档执行 geoNear。

有什么方法可以对这些数据执行这两项任务?如果是这样,我应该如何构建我的数据?如果没有,有没有一种方法可以让我执行一个查询,然后对第一个查询的结果执行第二个查询?

感谢您的帮助!

【问题讨论】:

【参考方案1】:

在 mongodb 中存储层次结构还有另一种选择(除了嵌入和规范化),即将它们存储为 tree structures。在这种情况下,您会将买家和商品存储在单独的文档中,但在同一个集合中。每个 Item 文档都需要一个指向其 Buyer(父)文档的字段,并且每个 Buyer 文档的父字段都将设置为 null。我链接的文档解释了您可以选择的几种实现。

【讨论】:

【参考方案2】:

如果您的项目存储在两个单独的集合中,那么最好的选择是编写您自己的函数并使用mongoose.connection.db.eval('some code...'); 调用它。在这种情况下,您可以在服务器端执行您的高级逻辑。

你可以这样写:

var allNearItems = db.Items.find(
     location: 
        $near: 
            $geometry: 
              type: "Point" ,
              coordinates: [ <longitude> , <latitude> ]
            ,
            $maxDistance: 100
        
    
); 
var res = [];
allNearItems.forEach(function(item)
    var buyer = db.Buyers.find( id: item.buyerId )[0];
    if (!buyer) continue;
    if (item.bid < buyer.credit) 
        res.push(item.id);
    
);
return res;

评估后(将其放在mongoose.connection.db.eval("...") 调用中),您将获得项目ID 的数组。

谨慎使用。如果你的 allNearItems 数组太大或者你会经常查询它,你可能会遇到性能问题。 MongoDB 团队实际上已经弃用了直接执行 js 代码,但它在当前稳定版本中仍然可用。

【讨论】:

以上是关于MongoDB - 查询难题 - 文档参考或子文档的主要内容,如果未能解决你的问题,请参考以下文章

Mongoid / Mongodb 和查询嵌入文档

MongoDB查询集合中的文档

怎么使用java操作mongodb更新整个文档

mongodb官方文档中没有专门讲锁机制的章节吗

mongodb查询速度慢是啥原因

mongodb 命令行用啥命令查询Collection文档结构