Spring 数据 MongoDb - 与使用 $expr 的给定查询等效的条件
Spring Data MongoDb - Criteria equivalent to a given query that uses $expr
我有一个 collection 文件是这样的:
{
"_id" : ObjectId("5a8ec4620cd3c2a4062548ec"),
"start" : 20,
"end" : 80
}
并且我想显示以一定间隔(startInterval = 10,endInterval = 90)重叠给定百分比 (50%) 的文档。
我用下面的公式计算重叠部分:
min(end , endInterval) - max(start, startInterval ) / (endInterval - startInterval)
在这个例子中:
最小值 (80,90) - 最大值 (20,10) / (90-10) = (80-20)/80 = 0.75 --> 75%
然后会显示这个文档,因为75%大于50%
我在mongoshell中将这个公式表示为:
db.getCollection('variants').find(
{
$expr: {
$gt: [
{
$divide: [
{
$subtract: [
{ $min: [ "$end", endInterval ] }
,
{ $max: [ "$start", startInterval ] }
]
}
,
{ $subtract: [ endInterval, startInterval ] }
]
}
,
overlap
]
}
}
)
哪里
overlap = 0.5,startInterval = 10 和 endInterval= 90
它在 mongo shell.
中工作正常
我要求使用 Spring 数据标准进行计算的等效方法,因为我在 mongo shell 中使用的 $expr 功能仍将在 Spring数据Mongo。
目前我正在使用 Spring Boot 2.0.0,Spring Data MongoDb 2.0.5 和 mongodb 3.6.
非常感谢您的宝贵时间。
以防万一它对某人有帮助,我终于使用 $redact 解决了我的问题。
String redact = "{\n" +
" \"$redact\": {\n" +
" \"$cond\": [\n" +
" {\n" +
" \"$gte\": [\n" +
" {\n" +
" \"$divide\": [\n" +
" {\n" +
" \"$subtract\": [\n" +
" {\n" +
" \"$min\": [\n" +
" \"$end\",\n" +
" " + endInterval + "\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$max\": [\n" +
" \"$start\",\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$subtract\": [\n" +
" " + endInterval + "\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" " + overlap + "\n" +
" ]\n" +
" },\n" +
" \"$$KEEP\",\n" +
" \"$$PRUNE\"\n" +
" ]\n" +
" }\n" +
" }";
RedactAggregationOperation redactOperation = new RedactAggregationOperation(
Document.parse(redact)
);
其中 Redact AggregationOperation 是
public class RedactAggregationOperation implements AggregationOperation {
private Document operation;
public RedactAggregationOperation (Document operation) {
this.operation = operation;
}
@Override
public Document toDocument(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
正如你所说,Spring数据Mongo目前不支持$expr
,所以我必须使用自定义BSON文档,以及MongoTemplate
的反射。
public List<Variant> listTest() throws Exception {
double overlap = 0.5;
int startInterval = 10;
int endInterval= 90;
String jsonQuery = "{$expr:{$gt:[{$divide:[{$subtract:[{$min:[\"$end\","+endInterval+"]},{$max:[\"$start\","+startInterval+"]}]},{$subtract:["+endInterval+","+startInterval+"]}]},"+overlap+"]}}";
Document query = Document.parse(jsonQuery);
Method doFind = MongoTemplate.class.getDeclaredMethod("doFind", String.class, Document.class,Document.class,Class.class);
doFind.setAccessible(true);
return (List<Variant>) doFind.invoke(mongoTemplate, "variants", query, new Document(), Variant.class);
}
@NoArgsConstructor @Getter @Setter @ToString
public static class Variant{
int start;
int end;
}
如您所见,字段映射工作正常。
使用的Spring数据Mongo神器是org.springframework:data.spring-data-mongodb:2.1.5.RELEASE
添加对 $expr
支持的未解决问题:https://github.com/spring-projects/spring-data-mongodb/issues/2750
同时,您可以使用 BasicQuery:
BasicQuery query = new BasicQuery("{ $expr: {'$gt': ['$results.cache.lastHit', '$results.cache.expiration']}}");
return ofNullable(mongoTemplate.findAndModify(query, updateDefinition, XXXX.class));
您甚至可以将现有条件与 BasicQuery 连接起来,使其独占 $expr
:
Criteria criteria = Criteria.where("results.cache.cacheUpdateRetriesLeft").gt(4);
BasicQuery query = new BasicQuery("{ $expr: {'$gt': ['$results.cache.lastHit', '$results.cache.expiration']}}");
query.addCriteria(criteria);
return ofNullable(mongoTemplate.findAndModify(query, updateDefinition, XXXX.class));
我有一个 collection 文件是这样的:
{
"_id" : ObjectId("5a8ec4620cd3c2a4062548ec"),
"start" : 20,
"end" : 80
}
并且我想显示以一定间隔(startInterval = 10,endInterval = 90)重叠给定百分比 (50%) 的文档。
我用下面的公式计算重叠部分:
min(end , endInterval) - max(start, startInterval ) / (endInterval - startInterval)
在这个例子中: 最小值 (80,90) - 最大值 (20,10) / (90-10) = (80-20)/80 = 0.75 --> 75% 然后会显示这个文档,因为75%大于50%
我在mongoshell中将这个公式表示为:
db.getCollection('variants').find(
{
$expr: {
$gt: [
{
$divide: [
{
$subtract: [
{ $min: [ "$end", endInterval ] }
,
{ $max: [ "$start", startInterval ] }
]
}
,
{ $subtract: [ endInterval, startInterval ] }
]
}
,
overlap
]
}
}
)
哪里
overlap = 0.5,startInterval = 10 和 endInterval= 90
它在 mongo shell.
中工作正常我要求使用 Spring 数据标准进行计算的等效方法,因为我在 mongo shell 中使用的 $expr 功能仍将在 Spring数据Mongo。 目前我正在使用 Spring Boot 2.0.0,Spring Data MongoDb 2.0.5 和 mongodb 3.6.
非常感谢您的宝贵时间。
以防万一它对某人有帮助,我终于使用 $redact 解决了我的问题。
String redact = "{\n" +
" \"$redact\": {\n" +
" \"$cond\": [\n" +
" {\n" +
" \"$gte\": [\n" +
" {\n" +
" \"$divide\": [\n" +
" {\n" +
" \"$subtract\": [\n" +
" {\n" +
" \"$min\": [\n" +
" \"$end\",\n" +
" " + endInterval + "\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$max\": [\n" +
" \"$start\",\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$subtract\": [\n" +
" " + endInterval + "\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" " + overlap + "\n" +
" ]\n" +
" },\n" +
" \"$$KEEP\",\n" +
" \"$$PRUNE\"\n" +
" ]\n" +
" }\n" +
" }";
RedactAggregationOperation redactOperation = new RedactAggregationOperation(
Document.parse(redact)
);
其中 Redact AggregationOperation 是
public class RedactAggregationOperation implements AggregationOperation {
private Document operation;
public RedactAggregationOperation (Document operation) {
this.operation = operation;
}
@Override
public Document toDocument(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
正如你所说,Spring数据Mongo目前不支持$expr
,所以我必须使用自定义BSON文档,以及MongoTemplate
的反射。
public List<Variant> listTest() throws Exception {
double overlap = 0.5;
int startInterval = 10;
int endInterval= 90;
String jsonQuery = "{$expr:{$gt:[{$divide:[{$subtract:[{$min:[\"$end\","+endInterval+"]},{$max:[\"$start\","+startInterval+"]}]},{$subtract:["+endInterval+","+startInterval+"]}]},"+overlap+"]}}";
Document query = Document.parse(jsonQuery);
Method doFind = MongoTemplate.class.getDeclaredMethod("doFind", String.class, Document.class,Document.class,Class.class);
doFind.setAccessible(true);
return (List<Variant>) doFind.invoke(mongoTemplate, "variants", query, new Document(), Variant.class);
}
@NoArgsConstructor @Getter @Setter @ToString
public static class Variant{
int start;
int end;
}
如您所见,字段映射工作正常。
使用的Spring数据Mongo神器是org.springframework:data.spring-data-mongodb:2.1.5.RELEASE
添加对 $expr
支持的未解决问题:https://github.com/spring-projects/spring-data-mongodb/issues/2750
同时,您可以使用 BasicQuery:
BasicQuery query = new BasicQuery("{ $expr: {'$gt': ['$results.cache.lastHit', '$results.cache.expiration']}}");
return ofNullable(mongoTemplate.findAndModify(query, updateDefinition, XXXX.class));
您甚至可以将现有条件与 BasicQuery 连接起来,使其独占 $expr
:
Criteria criteria = Criteria.where("results.cache.cacheUpdateRetriesLeft").gt(4);
BasicQuery query = new BasicQuery("{ $expr: {'$gt': ['$results.cache.lastHit', '$results.cache.expiration']}}");
query.addCriteria(criteria);
return ofNullable(mongoTemplate.findAndModify(query, updateDefinition, XXXX.class));