Java 在mongodb中查询符合条件的文档及其所有子文档(使用spring)
我有一个MongoDB存储来自不同传感器的数据。其结构如下:Java 在mongodb中查询符合条件的文档及其所有子文档(使用spring),java,mongodb,spring-data,spring-mongo,spring-mongodb,Java,Mongodb,Spring Data,Spring Mongo,Spring Mongodb,我有一个MongoDB存储来自不同传感器的数据。其结构如下: { "_id" : 1, "sensorName" : "Heart Rate", "samplePeriod" : 1000, "data" : [ { "timestamp" : NumberLong("1483537204046"), "dataPoints" : [ 68 70 ]
{
"_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]
}]
}
}
}
}
}])
但是我如何在JavaSpring数据中做到这一点呢?在spring数据中似乎没有什么比$filter更好的了。有解决办法吗
美元过滤器到底有多高效?
您能想出一种更有效/更实用的方法在mongodb中构建此类数据吗
提前谢谢 您需要使用spring mongo数据依赖项中提供的MongoTemplate。当前版本中没有对$filter的现成支持。利用攻击性的表情。在项目中包括以下投影。使用1.8.5 spring mongo数据版本
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(1)),
project( "_id", "sensorName", "samplePeriod").and(new AggregationExpression() {
@Override
public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
DBObject filter = new BasicDBObject("input", "$data").append("as", "result").append("cond",
new BasicDBObject("$and", Arrays.<Object> asList(new BasicDBObject("$gte", Arrays.<Object> asList("$$result.timestamp", 1483537204000L)),
new BasicDBObject("$lte", Arrays.<Object> asList("$$result.timestamp", 1483537214000L)))));
return new BasicDBObject("$filter", filter);
}
}).as("data")
);
List<BasicDBObject> dbObjects = monoTemplate.aggregate(aggregation, "collectionname", BasicDBObject.class).getMappedResults();
Aggregation=newAggregation(
匹配(标准,其中(“_id”)为(1)),
项目(“\u id”、“sensorName”、“samplePeriod”)和(新的AggregationExpression(){
@凌驾
公共数据库对象toDbObject(聚合操作上下文聚合操作上下文){
DBObject filter=newBasicDBObject(“输入”,“$data”).append(“作为”,“结果”).append(“条件”,
新的BasicDBObject(“$and”,Arrays.asList)(新的BasicDBObject(“$gte”,Arrays.asList(“$$result.timestamp”,1483537204000L)),
新的BasicDBObject(“$lte”,Arrays.asList(“$$result.timestamp”,1483537214000L())”);
返回新的BasicDBObject(“$filter”,filter);
}
}).as(“数据”)
);
List dbObjects=monoTemplate.aggregate(聚合,“collectionname”,BasicDBObject.class).getMappedResults();
您需要使用spring mongo数据依赖项中提供的MongoTemplate。当前版本中没有对$filter的现成支持。利用攻击性的表情。在项目中包括以下投影。使用1.8.5 spring mongo数据版本
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(1)),
project( "_id", "sensorName", "samplePeriod").and(new AggregationExpression() {
@Override
public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
DBObject filter = new BasicDBObject("input", "$data").append("as", "result").append("cond",
new BasicDBObject("$and", Arrays.<Object> asList(new BasicDBObject("$gte", Arrays.<Object> asList("$$result.timestamp", 1483537204000L)),
new BasicDBObject("$lte", Arrays.<Object> asList("$$result.timestamp", 1483537214000L)))));
return new BasicDBObject("$filter", filter);
}
}).as("data")
);
List<BasicDBObject> dbObjects = monoTemplate.aggregate(aggregation, "collectionname", BasicDBObject.class).getMappedResults();
Aggregation=newAggregation(
匹配(标准,其中(“_id”)为(1)),
项目(“\u id”、“sensorName”、“samplePeriod”)和(新的AggregationExpression(){
@凌驾
公共数据库对象toDbObject(聚合操作上下文聚合操作上下文){
DBObject filter=newBasicDBObject(“输入”,“$data”).append(“作为”,“结果”).append(“条件”,
新的BasicDBObject(“$and”,Arrays.asList)(新的BasicDBObject(“$gte”,Arrays.asList(“$$result.timestamp”,1483537204000L)),
新的BasicDBObject(“$lte”,Arrays.asList(“$$result.timestamp”,1483537214000L())”);
返回新的BasicDBObject(“$filter”,filter);
}
}).as(“数据”)
);
List dbObjects=monoTemplate.aggregate(聚合,“collectionname”,BasicDBObject.class).getMappedResults();
我认为通过使用放松和额外的比赛也可以达到同样的效果。SpringMongo驱动程序确实提供了对放松的支持,而且看起来更干净
aggregate([{
$match: {
"_id": 1
}
}, {
$unwind : "$data"
},{
$match : {'data.timestamp' : {$gte : 1483537204000, $lte : 1483537214000}}
}, {
$group : {
_id : $_id,
data : {$push:$data}
}
}])
我认为通过放松和额外的比赛也可以达到同样的效果。SpringMongo驱动程序确实提供了对放松的支持,而且看起来更干净
aggregate([{
$match: {
"_id": 1
}
}, {
$unwind : "$data"
},{
$match : {'data.timestamp' : {$gte : 1483537204000, $lte : 1483537214000}}
}, {
$group : {
_id : $_id,
data : {$push:$data}
}
}])
发布(截至编写时)已完成,可按如下方式实现:
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")
)
发布(截至编写时)已完成,可按如下方式实现:
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")
)
如果您计划使用Spring,我强烈建议您使用Spring数据,它将为您提供处理此类查询的方法。我已经在使用Spring数据(在本文中对此进行了更改)。我只有在创建新聚合时才会遇到困难。我可以“匹配”、“项目”,但不能“过滤”。看看这篇文章,我想如果你打算用Spring做这件事,你需要的是什么,我强烈建议你使用Spring数据,它将为你提供处理这类查询的方法。我已经在使用Spring数据了(在文本中对此进行了更改)。我只有在创建新聚合时才会遇到困难。我可以“匹配”、“项目”,但不能“筛选”。看看这篇文章,我想这是你需要的,但在大文档上,放松速度很慢,因为它会为每个条目创建单独的文档,不是吗?我想避免这种情况。相比之下,“过滤器”的性能如何?是什么让你认为放松会很慢?在我看来,如果不比投射阶段的过滤速度快,也一样,在投射阶段,每个数据都通过条件传递和解析。放松也给了我们手去做更复杂的动作。另外,如果您正在为一个具有16MB限制的文档执行操作,您将无法看到其中任何一个文档的性能差异。这并不完全正确。过滤器是就地操作。这可能与你的具体情况无关。如果您有大型文档,性能将受到影响。这是为过滤器量身定制的外壳。“你为什么要在没有必要的时候放松呢?”SagarReddy说,“这是感知,不是吗?”?对你来说,不需要放松,对我来说,投影内部不需要复杂的过滤操作。仅仅因为它在原地并不意味着它更好。之所以称之为“聚合”,是因为数据看起来是干净聚合的,而不是每个内部数据都使用过滤条件进行变形。但你当然有权发表你的意见。只是澄清一下,这并不取决于你的看法。我会让OP来决定。但是在大文档上展开很慢,因为它会为每个条目创建单独的文档,不是吗?我想避免这种情况。相比之下,“过滤器”的性能如何?是什么让你认为放松会很慢?在我看来,如果不比投射阶段的过滤速度快,也一样,在投射阶段,每个数据都通过条件传递和解析。放松也给了我们手去做更复杂的动作。另外,如果您正在为一个文档执行以下操作: