如何在JavaSpring的mongoTemplate聚合中实现$SetIsSubset?

How to implement $SetIsSubset in mongoTemplate aggregation of Java Spring?

我正在尝试在 mongoTemplate 聚合中使用 $setIsSubset class。但是找不到任何解决方案。

我的Mongo查询是:

db.events.aggregate([
    { $match: { $and: [ 
        { "event_state" : {$in : ["live","scheduled"]} }, 
        { "schedule.end_time" : {$gt : ISODate("2016-12-12T06:30:00.000Z")} }
        ] 
      } 
    },
    {$project: 
        { 
            "name" :1, 
            "category" :1,
            "schedule":1, 
            "celebrity" :1,
            "online_moderator" :1,
            "offline_moderator" :1,
            "region" :1,
            "status" :1,
            "event_state" :1,
            "recorder_id" :1,
            "webcast_url":1,
            "replay_url":1,
            "registered_users":1,
            registeredUsers: { $size:"$registered_users" },
            is_registered:
            { $setIsSubset: [[ObjectId("584e6253e17ed10f0a8cba1d"),ObjectId("583e9719e17e8c1bf80da2fe")], "$registered_users.user_id"]}
        }
    },
    { $sort : {
            "schedule.start_time": 1
        }
    }
]);

我已经转换了大部分代码,如下所示。但是遇到了 $setIsSubset 条件。

matchCondition = Aggregation.match(Criteria.where("event_state")
                    .in(listEventStates).and("schedule.end_time").gt(d));

AggregationOperation projectValues = Aggregation.project()
                .and("registered_users").size().as("registered_users_count")
                .and("name").as("name").and("category").as("category")
                .and("schedule").as("schedule").and("online_moderator")
                .as("online_moderator").and("offline_moderator")
                .as("offline_moderator").and("region").as("region")
                .and("status").as("status").and("event_state")
                .as("event_state").and("recorder_id").as("recorder_id")
                .and("webcast_url").as("webcast_url").and("replay_url")
                .as("replay_url");

sortCondition = Aggregation.sort(Sort.Direction.ASC,
                    "schedule.start_time");

Aggregation aggrigation = Aggregation.newAggregation(matchCondition,
                sortCondition, projectValues);

编辑:

根据@user_531 的要求。我正在用对我有用的可能解决方案更新我的问题。我不知道它是否会起作用,因为我使用该解决方案已经 2 年了。之后又改了几次代码,就不再维护这个项目了。但值得一试。

AggregationOperation projectValues = Aggregation.project().and("registered_users").size()
            .as("registered_users_count").and("event_image").as("event_image")
            .and("name").as("name").and("category").as("category").and("schedule").as("schedule")
            .and("region").as("region").and("status").as("status").and("event_state").as("event_state")
            .and("recorder_id").as("recorder_id").and("webcast_url").as("webcast_url").and("replay_url")
            .as("replay_url").and("registered_users").as("registered_users").and("room_details").as("room_details")
            .and("live_stream_url").as("live_stream_url")
            .and(new AggregationExpression() {        
                public DBObject toDbObject(AggregationOperationContext context) {
                    return new BasicDBObject("$setIsSubset", Arrays.<Object> asList(
                    Arrays.<Object> asList(new ObjectId("58528314e17edbb252692815")),
                        "$registered_users.user_id")); 
                } 
            }).as("is_registered");

    Aggregation aggrigation = Aggregation.newAggregation(matchCondition, sortCondition, projectValues);

    AggregationResults<Events> results = mongoTemplate.aggregate(aggrigation, "events", Events.class);

您可以使用 Mongodb api 用于项目 (com.mongodb.client.model.Aggregates.project) 也可以用于匹配 (com.mongodb.client.model.Aggregates.match(Bson 过滤器)) 您可以使用我刚刚完成的代码,例如使用 $setIsSubset

使用此查询

db.getCollection('collection').aggregate(
 {    $match : {"_id" : "dff26f9c-350b-4bd5-bc62-62c19f21100c"}   },
{ "$project": {
       "sensorId": 1,   "sensorModel": 1,
   "attachments": {
     "$filter": {
   "input": "$attachments",
   "as": "attachment",
   "cond": {
     "$setIsSubset": [
       ["$$attachment.type"],
       ["StructAttachment", "BlobAttachment"]
     ]
   }    }   } }})

java 代码如下:

List <Bson> aggregationInput = new ArrayList <Bson> ();
aggregationInput.add(match(eq("_id",id)));
HashMap<String, Integer> fieldsMap=new HashMap<String, Integer>();
fieldsMap.put("sensorId", 1);
fieldsMap.put("sensorModel", 1);

ArrayList< ArrayList<String>> isSubset = new ArrayList< ArrayList<String>>();
ArrayList<String> isSubsetParameter1 = new ArrayList<String>();
isSubsetParameter1.add("$$attachment.mimeType");

ArrayList<String> isSubsetParameter2 = new ArrayList<String>();
isSubset.add(isSubsetParameter1 );
isSubset.add(isSubsetParameter2 );

Document docFields = new Document();
if (mimeTypes == null || mimeTypes.isEmpty()) {

//mimeTypes是一个Set isSubsetParameter2.addAll(mimeTypes);

Document filter = new Document();
filter.put("input", "$attachments");
filter.put("as", "attachment");
filter.put("cond", new  Document("$setIsSubset", isSubset));

docFields.put("attachments", new Document("$filter",filter));
docFields.putAll(fieldsMap);
aggregationInput.add(project(docFields));

AggregateIterable<Document> resultIteratr = mongo.getDatabase("db").getCollection("collection")
.aggregate(aggregationInput);

希望这对你有用!

利用AggressionExpression。在项目中包含以下投影。使用1.8.5springmongo数据版本

and(new AggregationExpression() {
    @Override
    public DBObject toDbObject(AggregationOperationContext context) {
        return new BasicDBObject("$setIsSubset",
                Arrays.<Object> asList(
                        Arrays.<Object> asList("584e6253e17ed10f0a8cba1d",
                                "583e9719e17e8c1bf80da2fe"),
                        "$registered_users.user_id"));
    }
}).as("is_registered"));

您可以将表达式包装为 Java 8

的 lambda
and(context -> new BasicDBObject("$setIsSubset",
        Arrays.<Object> asList(
                Arrays.<Object> asList("584e6253e17ed10f0a8cba1d",
                         "583e9719e17e8c1bf80da2fe"),
                "$registered_users.user_id")))
.as("is_registered"));