我有一个MongoDB存储来自不同传感器的数据。它具有以下结构:
{
"_id" : 1,
"sensorName" : "Heart Rate",
"samplePeriod" : 1000,
"data" : [
{
"timestamp" : NumberLong("1483537204046"),
"dataPoints" : [ 68 70 ]
},
{
"timestamp" : NumberLong("1483537206046"),
"dataPoints" : [ 68 70 ]
}
]
}
{
"_id" : 2,
"sensorName" : "Ambient Light",
"samplePeriod" : 500,
"data" : [
{
"timestamp" : NumberLong("1483537204058"),
"dataPoints" : [ 56, 54, 54, 54 ]
},
{
"timestamp" : NumberLong("1483537206058"),
"dataPoints" : [ 56, 54, 54, 54 ]
}
]
}
现在我需要“心率” - 包含其所有字段及其“数据”字段的文档 - 符合条件“1483537204000和1483537214000之间的时间戳”的子文档。
我已经在另一个问题的mongo shell中得到了关于如何做到这一点的答案。看到这段代码:
aggregate([{
$match: {
"_id": 1
}
}, {
"$project": {
"_id": 1,
"sensorName": 1,
"samplePeriod": 1,
"data": {
"$filter": {
"input": "$data",
"as": "result",
"cond": {
$and: [{
$gte: ["$$result.timestamp", 1483537204000]
}, {
$lte: ["$$result.timestamp", 1483537214000]
}]
}
}
}
}
}])
但是我如何在java spring-data中执行此操作?在spring-data中似乎没有像$ filter那样的东西。有解决方法吗?
$ filter的效率如何? 你能想到在mongodb中构建这种数据的更有效/实用的方法吗?
提前致谢!
答案 0 :(得分:0)
您需要使用spring mongo数据依赖项中提供的MongoTemplate。当前版本中没有对$ filter的开箱即用支持。利用AggressionExpression。在项目中包括以下投影。使用1.8.5 spring mongo数据版本。
class Animal {
constructor(text) {
this.speech = text;
}
static get name() {
return "Animal";
}
get name() {
return this.constructor.name;
}
speak() {
console.log( this.name + ":"+ this.speech)
}
}
class Tiger extends Animal {
static get name() {
return "Tiger"
}
}
var animal = new Animal("hey there");
animal.speak();
var tiger = new Tiger("hello");
tiger.speak();
答案 1 :(得分:0)
我认为通过使用展开和额外匹配可以实现同样的目的。 Spring mongo驱动程序确实提供了放松支持,看起来更干净。
aggregate([{
$match: {
"_id": 1
}
}, {
$unwind : "$data"
},{
$match : {'data.timestamp' : {$gte : 1483537204000, $lte : 1483537214000}}
}, {
$group : {
_id : $_id,
data : {$push:$data}
}
}])
答案 2 :(得分:0)
Spring Data MongoDB 1.10 RC1 (Ingalls), 2.0 M2 (Kay)版本(截至撰写时)有added support for $filter
,可以按如下方式实现:
Aggregation.newAggregation(Entity.class,
match(Criteria.where("_id").is(1)),
project("sensorName", "samplePeriod")
.and(
filter("data")
.as("item")
.by(
GTE.of(field("item.timestamp"), 1483537204000)
.LTE.of(field("item.timestamp"), 1483537214000)
)
).as("data")
)