10

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

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

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

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

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

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

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

谢谢你的帮助!

4

2 回答 2

3

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

于 2015-05-06T23:25:44.413 回答
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 代码,但它在当前稳定版本中仍然可用。

于 2015-05-12T15:07:35.137 回答