我有这种结构的mongo数据库:
我需要在时间范围之间获取父文档及其子文档。 我使用nodejs mongoosejs驱动程序。这是我目前的要求:
var searchQueryTerminal = TickModel
.findOne({
symbol:symbol,
'tickData.timestamp':{
$gte:dateStart,
$lte:dateEnd
},
broker:{$in: broker},
MTVersion:MTVersion
});
我在结果中有1个父文档,正如预期的那样,但它包含所有子文档,不仅包括时间范围。如何使用猫鼬驱动程序以正确的方式执行此操作?我不是真的想在节点端做这件事,因为子文档的数量可能是几百万。
架构:
var TickDataSchema = new mongoose.Schema({
bid: Number,
ask: Number,
timestamp: {
type:Date,
default:Date.now,
expires: '7d'
}});
var TickSchema = new mongoose.Schema({
broker:{
type: String,
index:true
},
account: Number,
symbol: {
type: String,
index:true
},
MTVersion:Number,
key: {
type:String,
index:true
},
tickData:[TickDataSchema]
});
答案 0 :(得分:1)
使用implementation的Mongoose $elemMatch
。在mongo中使用以下集合进行测试:
db.test.insert([
{ "symbol": "AMBC", "MTVersion": 0.25, "tickData": [{ "bid": 1, "ask": 1.5, "timestamp": ISODate("2015-01-28T08:00:00.000Z") }, { "bid": 1, "ask": 1.3, "timestamp": ISODate("2015-01-21T08:00:00.000Z") }] },
{ "symbol": "MSFT", "MTVersion": 0.25, "tickData": [{ "bid": 1, "ask": 1.5, "timestamp": ISODate("2015-02-04T08:00:00.000Z") }, { "bid": 1, "ask": 1.3, timestamp: ISODate("2015-02-11T08:00:00.000Z") }] }
]);
var symbol = "AMBC",
dateStart = new Date (2015, 0, 20),
dateEnd = new Date(2015, 0, 22),
MTVersion = 0.25;
db.test.findOne({
"symbol": symbol,
"tickData.timestamp": {
"$gte": dateStart,
"$lte": dateEnd
},
"MTVersion": MTVersion
}, {
"symbol": 1,
"MTVersion": 1,
"tickData": {
"$elemMatch": {
"timestamp": {
"$gte": dateStart,
"$lte": dateEnd
}
}
}
});
<强>返回强>:
/* 0 */
{
"_id" : ObjectId("5530f8c4180e849972938fdf"),
"symbol" : "AMBC",
"MTVersion" : 0.25,
"tickData" : [
{
"bid" : 1,
"ask" : 1.3,
"timestamp" : ISODate("2015-01-21T08:00:00.000Z")
}
]
}
所以在Mongoose中,你可以做类似的事情:
TickModel
.findOne({
symbol: symbol,
broker: {$in: broker},
MTVersion: MTVersion
})
.elemMatch("tickData", { "timestamp": {"$gte": dateStart, "$lte": dateEnd } })
// .select({"tickData": { "$elemMatch": { "timestamp": {"$gte": dateStart, "$lte": dateEnd } }, "symbol": 1, "MTVersion": 1, "broker": 1 })
.exec(cb);
使用聚合框架,可以通过以下管道实现:
var pipeline = [
{
"$match": {
"symbol": symbol,
"tickData.timestamp": {
"$gte": dateStart,
"$lte": dateEnd
},
"MTVersion": MTVersion
}
},
{
"$unwind": "$tickData"
},
{
"$match": {
"tickData.timestamp": {
"$gte": dateStart,
"$lte": dateEnd
}
}
},
{
"$group": {
_id: {
"id": "$_id",
"broker": "$broker",
"account": "$account"
"symbol": "$symbol",
"MTVersion": "$MTVersion",
"key": "$key"
},
"tickData": {
"$addToSet": "$tickData"
}
}
},
{
"$project": {
"_id": 0,
"tickData": 1,
"broker": "$_id.broker",
"account": "$_id.account"
"symbol": "$_id.symbol",
"MTVersion": "$_id.MTVersion",
"key": "$_id.key"
}
}
];
TickModel.aggregate(pipeline, function (err, result) {
if (err) {
console.log(err);
return;
}
console.log(result);
});
结果:(使用上述样本文件)
/* 0 */
{
"result" : [
{
"tickData" : [
{
"bid" : 1,
"ask" : 1.3,
"timestamp" : ISODate("2015-01-21T08:00:00.000Z")
}
],
"symbol" : "AMBC",
"MTVersion" : 0.25
}
],
"ok" : 1
}
答案 1 :(得分:0)
您可以尝试填充功能
var searchQueryTerminal = TickModel
.findOne({
symbol:symbol,
broker:{$in: broker},
MTVersion:MTVersion
}).populate({
path: 'tickData',
match: { timestamp: { $gte:dateStart, $lte:dateEnd}},
})