MongoDB - 查询难题 - 文档引用或子文档

MongoDB - Query conundrum - Document refs or subdocument

我 运行 存储在 MongoDB 中的一些数据有点问题(注意:我使用 mongoose 作为 ODM)。我有两个模式:

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

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

Buyer/Item 将有一个 parent/child 关联,具有一对多关系。我知道我可以将 Items 设置为嵌入 Buyer 文档的子文档 or 我可以创建两个单独的文档,对象 ID 相互引用。

我面临的问题是我需要查询 出价低于买家信用额度 的项目,而且 位置靠近某个地理坐标的项目.

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

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

感谢您的帮助!

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

如果您的项目存储在两个单独的集合中,那么最好的选择是编写您自己的函数并使用 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 代码,但它在当前稳定版本中仍然可用。