MongoDB - child 中带有外键的 OneToMany
MongoDB - OneToMany with foreign key in child
我正在使用 mongodb v.2.6.11 和猫鼬。
我有两个具有 OneToMany 关系的模型。在我的 parent、TypeA(缩写为 TA)中,我没有引用 child。在我的 child、TypeB(缩写为 TB)中,我有一个对 parent 的 id 引用。
示例架构:
var TASchema = {
name: {type: String, required: "TASchema.name is required", index: {unique: true, dropDups: true}}
};
var TBSchema = {
start: {type: Number, required: "TBSchema.language is required"},
stop: {type: Number, required: "TBSchema.stop is required"},
TA: {type: Schema.Types.ObjectId, ref: 'tbschema'},
}
我想要做的:Select 所有在两个变量 "ts_start" 和 "ts_stop" 的时间跨度内具有 "start" 变量的 TB(它们是时间戳).所以类似于:start : {$gte: ts_min, $lte : ts_max}
。
示例输出:
[
{
name: "Ta object 1",
tbs: [{start : 1, stop2}, {start: 2, stop: 3}]
},
{
name: "Ta object 2",
tbs: [{start : 1, stop2}, {start: 2, stop: 3}]
}
]
我想保留结构,其中查询 returns 一个 TA 数组,其中每个 TA 包含一个 TB:s 数组。但是我不能使用 populate
,因为 TA 没有对 child 的任何引用(因为可能有太多的内容而无法将它们作为子文档)。
那么这是如何实现的呢?我是不是想错了,或者我应该怎么做才能像我的示例输出中那样输出指定的查询?
搭载@vmkcom,尝试聚合框架通过$match
and $group
管道步骤实现这一点,使用从管道操作返回的结果然后填充TA字段,但 TA 模型的架构设计发生了变化。这对于填充聚合结果是必要的,因此在您的 TA 模式中向 TB 模式添加一个引用数组:
var TASchema = {
name: {
type: String,
required: "TASchema.name is required",
index: {unique: true, dropDups: true}
},
tbs: [{ type: Schema.Types.ObjectId, ref: 'tbschema' }]
};
实现如下(未经测试):
var pipeline = [
{
"$match": {
"start": { "$gte": ts_min, "$lte": ts_max }
}
},
{
"$group": {
"_id": "$TA",
"tbs": {
"$push": { "start": "$start", "stop": "$stop" }
}
}
}
];
TBModel.aggregate(pipeline,
function(err, results) {
if (err) throw err;
var results = result.map(function(doc) { return new TAModel(doc) });
TBModel.populate(results, {"path": "TA"}, function(err, docs) {
if (err) throw err;
console.log(JSON.stringify(docs, undefined, 4));
});
}
);
我正在使用 mongodb v.2.6.11 和猫鼬。
我有两个具有 OneToMany 关系的模型。在我的 parent、TypeA(缩写为 TA)中,我没有引用 child。在我的 child、TypeB(缩写为 TB)中,我有一个对 parent 的 id 引用。
示例架构:
var TASchema = {
name: {type: String, required: "TASchema.name is required", index: {unique: true, dropDups: true}}
};
var TBSchema = {
start: {type: Number, required: "TBSchema.language is required"},
stop: {type: Number, required: "TBSchema.stop is required"},
TA: {type: Schema.Types.ObjectId, ref: 'tbschema'},
}
我想要做的:Select 所有在两个变量 "ts_start" 和 "ts_stop" 的时间跨度内具有 "start" 变量的 TB(它们是时间戳).所以类似于:start : {$gte: ts_min, $lte : ts_max}
。
示例输出:
[
{
name: "Ta object 1",
tbs: [{start : 1, stop2}, {start: 2, stop: 3}]
},
{
name: "Ta object 2",
tbs: [{start : 1, stop2}, {start: 2, stop: 3}]
}
]
我想保留结构,其中查询 returns 一个 TA 数组,其中每个 TA 包含一个 TB:s 数组。但是我不能使用 populate
,因为 TA 没有对 child 的任何引用(因为可能有太多的内容而无法将它们作为子文档)。
那么这是如何实现的呢?我是不是想错了,或者我应该怎么做才能像我的示例输出中那样输出指定的查询?
搭载@vmkcom,尝试聚合框架通过$match
and $group
管道步骤实现这一点,使用从管道操作返回的结果然后填充TA字段,但 TA 模型的架构设计发生了变化。这对于填充聚合结果是必要的,因此在您的 TA 模式中向 TB 模式添加一个引用数组:
var TASchema = {
name: {
type: String,
required: "TASchema.name is required",
index: {unique: true, dropDups: true}
},
tbs: [{ type: Schema.Types.ObjectId, ref: 'tbschema' }]
};
实现如下(未经测试):
var pipeline = [
{
"$match": {
"start": { "$gte": ts_min, "$lte": ts_max }
}
},
{
"$group": {
"_id": "$TA",
"tbs": {
"$push": { "start": "$start", "stop": "$stop" }
}
}
}
];
TBModel.aggregate(pipeline,
function(err, results) {
if (err) throw err;
var results = result.map(function(doc) { return new TAModel(doc) });
TBModel.populate(results, {"path": "TA"}, function(err, docs) {
if (err) throw err;
console.log(JSON.stringify(docs, undefined, 4));
});
}
);