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 代码,但它在当前稳定版本中仍然可用。
我 运行 存储在 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 代码,但它在当前稳定版本中仍然可用。