Spring Data MongoDB构建动态查询

时间:2018-06-15 12:32:44

标签: spring mongodb mongodb-query spring-data-mongodb

需要帮助来构建动态MongoDB查询。 “$或”数组中的所有内容都是动态的。

db.group.find({ 
        "version" : NumberLong(0), 
        "$or" : [{
                "$and" : [
                    {
                        "object_type" : "D"
                    }, 
                    {
                        "type" : "R"
                    }, 
                    {
                        "name" : "1"
                    }
                ]
            },{
                "$and" : [
                    {
                        "object_type" : "D"
                    }, 
                    {
                        "type" : "E"
                    }, 
                    {
                        "name" : "2"
                    }
                ]
            ]
});

以下弹簧数据查询但是不起作用

Criteria criteria = Criteria.where("version").is("123");
        List<Criteria> docCriterias = new ArrayList<Criteria>();
        groups.stream().forEach(grp -> {
            docCriterias.add(Criteria.where("type").is(grp.get("type").toString())
                                .andOperator(Criteria.where("object_type").is(grp.get("objectType").toString()))
                                .andOperator(Criteria.where("name").is(grp.get("name").toString())));

        });
        criteria.orOperator((Criteria[]) docCriterias.toArray());
        Query q = new Query(criteria);

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

您应该注意如何组合操作员 ff代码应该适合你(请注意这是groovy记得将闭包更改为java lambda表达式):

List<Criteria> docCriterias = new ArrayList<Criteria>();

List groups = [
        [
                type: "type1",
                object_type: "object_type1",
                name: "name1"
        ],

        [
                type: "type2",
                object_type: "object_type2",
                name: "name2"
        ],

        [
                type: "type3",
                object_type: "object_type3",
                name: "name3"
        ],
]

groups.stream().each {grp ->

    docCriterias.add(new Criteria().andOperator(
            Criteria.where("type").is(grp.get("type")),
            Criteria.where("object_type").is(grp.get("object_type")),
            Criteria.where("name").is(grp.get("name"))
    ))


};


Criteria criteria = new Criteria().andOperator(
        Criteria.where("version").is("123"),
        new Criteria().orOperator(docCriterias.toArray(new Criteria[docCriterias.size()]))
);



Query q = new Query(criteria);

这将为您提供此查询:

{
   "$and":[
      {
         "version":"123"
      },
      {
         "$or":[
            {
               "$and":[
                  {
                     "type":"type1"
                  },
                  {
                     "object_type":"object_type1"
                  },
                  {
                     "name":"name1"
                  }
               ]
            },
            {
               "$and":[
                  {
                     "type":"type2"
                  },
                  {
                     "object_type":"object_type2"
                  },
                  {
                     "name":"name2"
                  }
               ]
            },
            {
               "$and":[
                  {
                     "type":"type3"
                  },
                  {
                     "object_type":"object_type3"
                  },
                  {
                     "name":"name3"
                  }
               ]
            }
         ]
      }
   ]
},
Fields:{

},
Sort:{

}

答案 1 :(得分:0)

您可以使用Json和Apache Velocity中的MongoDB Aggregation Pipeline来实现此功能,以自定义更多查询,然后使用Spring MongoTemplate使用db.runCommand来执行此操作。

示例: monodb_client_dynamic_query.vm

{
    "aggregate":  "client",
    "pipeline": [
        { 
            "$match" : {
                "$and" : [
                    {
                        "is_removed" : {
                            "$ne" : [
                                true
                            ]
                        }
                    }, 
                    {
                        "errors" : {
                            "$size" : 0.0
                        }
                    },
                    {
                        "client_id": "$velocityMap.client_id"
                    }
                ]
            }
        }, 
        { 
            "$project" : {
                "_id" : -1.0, 
                "account" : "$_id.account", 
                "person_id" : "$_id.person_id", 
                "begin_date": { $dateToString: { format: "%Y-%m-%d", date: "$value.begin_date" } },
               "end_date": { $dateToString: { format: "%Y-%m-%d", date: "$value.end_date" } }

            }

        }
     ]
}

然后使用MondoTemplate执行:

String script = ...load from file the script monodb_client_dynamic_query.vm
Map parameters = ... put all variables to  replace in the mongodb script
String scriptNoSql = VelocityUtil.loadTemplateVM(script, parameters);
DBObject dbObject = (BasicDBObject) JSON.parse(scriptNoSql);
if (null == dbObject) {
                    return;
}
DB db = mongoTemplate.getDb();
CommandResult result = db.command(dbObject);


if(!result.ok()) {
        throw result.getException();
}