首页 文章

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

提问于
浏览
10

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

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

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

买方/物品将具有父母/子女协会,具有一对多的关系 . 我知道我可以设置要嵌入子文件的项目到买方文档 or 我可以创建两个单独的文档,其中对象id引用彼此 .

我面临的问题是我需要查询Items where it's bid is lower than Buyer's credit ,还要查询 where location is near a certain geo coordinate .

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

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

谢谢你的帮助!

2 回答

  • 3

    还有另一个选项(除了嵌入和规范化)用于在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代码执行,但它仍然可用于当前的稳定版本 .

相关问题