简体   繁体   English

查询与mongodb中的条件匹配的文档及其所有子文档(使用spring)

[英]Query a document and all of its subdocuments that match a condition in mongodb (using spring)

I have a MongoDB storing data from different sensors. 我有一个MongoDB,用于存储来自不同传感器的数据。 It has the following structure: 它具有以下结构:

 {
     "_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 ]
            }
    ]
}

Now for example i need the "Heart Rate" - document with all of its fields and those of its "data" - subdocuments matching the condition "timestamp between 1483537204000 and 1483537214000". 现在,例如,我需要匹配所有条件和“时间戳记介于1483537204000和1483537214000之间”的子文档“ Heart Rate”(包含所有字段和“ data”的子文档)。

I already got the answer on how to do this in the mongo shell in another Question. 我已经在另一个问题中的mongo shell中获得了有关如何执行此操作的答案。 See this code: 参见以下代码:

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]
                    }]
                }
            }
        }
    }
}])

But how do I do this in java spring-data? 但是如何在java spring-data中做到这一点? It seems there is nothing like $filter in spring-data. 似乎在spring-data中没有像$ filter这样的东西。 Is there a workaround? 有解决方法吗?

How efficient is $filter anyway? 反之,$ filter的效率如何? Can you think of a more efficient/practical way of structuring this kind of data in mongodb? 您能想到在mongodb中构造此类数据的更有效/更实用的方法吗?

Thanks in advance! 提前致谢!

You'll need to make use of MongoTemplate provided in the spring mongo data dependency. 您需要利用spring mongo数据依赖项中提供的MongoTemplate。 There is no out of box support for $filter in the current release version. 当前发行版中没有对$ filter的现成支持。 Make use of AggressionExpression. 利用AggressionExpression。 Include below projection in project. 在项目中包括以下投影。 Use 1.8.5 spring mongo data version. 使用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();

I think the same can be achieved by the use of unwind and an extra match. 我认为使用放卷和额外的比赛可以达到同样的效果。 Spring mongo driver does provide support for unwind and it looks bit cleaner. Spring mongo驱动程序确实提供了对展开的支持,并且看起来更干净。

aggregate([{
 $match: {
    "_id": 1
   }
 }, {
  $unwind : "$data"
 },{
   $match : {'data.timestamp' : {$gte : 1483537204000, $lte : 1483537214000}}
 }, {
  $group : {
      _id : $_id,
      data : {$push:$data}
  }
 }])

The Spring Data MongoDB 1.10 RC1 (Ingalls), 2.0 M2 (Kay) releases (as of writing) have added support for $filter and this can be implemented as follows: Spring Data MongoDB 1.10 RC1(Ingalls),2.0 M2(Kay)发行版(在撰写本文时) 增加了对$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")
    )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM