来自 MongoDB 使用 spring 数据的随机文档
Random documents from MongoDB using spring-data
我可以用这个 mongodb native query:
db.books.aggregate(
[ { $sample: { size: 15 } } ]
)
但是在spring-data-mongodb
中如何做到呢?
中没有发现类似的操作
更新:
从 Spring 数据的 v2.0 开始,您可以这样做:
SampleOperation matchStage = Aggregation.sample(5);
Aggregation aggregation = Aggregation.newAggregation(sampleStage);
AggregationResults<OutType> output = mongoTemplate.aggregate(aggregation, "collectionName", OutType.class);
原回答:
像 spring-mongo 这样的抽象层总是落后于服务器发布的功能。所以你最好自己为管道阶段构建 BSON 文档结构。
在自定义中实施 class:
public class CustomAggregationOperation implements AggregationOperation {
private DBObject operation;
public CustomAggregationOperation (DBObject operation) {
this.operation = operation;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
然后在你的代码中使用:
Aggregation aggregation = newAggregation(
new CutomAggregationOperation(
new BasicDBObject(
"$sample",
new BasicDBObject( "size", 15 )
)
)
);
由于它实现了 AggregationOperation
,因此它与现有的管道操作辅助方法配合得很好。即:
Aggregation aggregation = newAggregation(
// custom pipeline stage
new CutomAggregationOperation(
new BasicDBObject(
"$sample",
new BasicDBObject( "size", 15 )
)
),
// Standard match pipeline stage
match(
Criteria.where("myDate")
.gte(new Date(new Long("949384052490")))
.lte(new Date(new Long("1448257684431")))
)
);
所以,归根结底,一切都只是一个 BSON 对象。这只是一个接口包装器的问题,以便 spring-mongo 中的 class 方法解释结果并正确获取您定义的 BSON 对象。
Blakes Seven 回答正确,但是,我想提供一个更好的 AggregationOperation 实现,它遵循标准 Spring
实施
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.Assert;
public class SampleOperation implements AggregationOperation {
private int size;
public SampleOperation(int size) {
Assert.isTrue(size > 0, " Size must be positive!");
this.size = size;
}
public AggregationOperation setSize(int size) {
Assert.isTrue(size > 0, " Size must be positive!");
this.size = size;
return this;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$sample", context.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
}
}
之后,您可以使用构造函数创建 SampleOperation 对象,或者稍后通过 setSize()
方法更改它的大小,并像往常一样将其应用于 aggregate()
函数。
更新:在 SpringBoot 2.0.0+ 和 Spring Framework 5.0 中:Spring Mongo 删除 DBObject
并替换为 org.bson.Document
因此最后的过去应该更新为:
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return new Document("$sample", aggregationOperationContext.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
}
并删除 @Override toDBObject
我可以用这个 mongodb native query:
db.books.aggregate(
[ { $sample: { size: 15 } } ]
)
但是在spring-data-mongodb
中如何做到呢?
更新:
从 Spring 数据的 v2.0 开始,您可以这样做:
SampleOperation matchStage = Aggregation.sample(5);
Aggregation aggregation = Aggregation.newAggregation(sampleStage);
AggregationResults<OutType> output = mongoTemplate.aggregate(aggregation, "collectionName", OutType.class);
原回答:
像 spring-mongo 这样的抽象层总是落后于服务器发布的功能。所以你最好自己为管道阶段构建 BSON 文档结构。
在自定义中实施 class:
public class CustomAggregationOperation implements AggregationOperation {
private DBObject operation;
public CustomAggregationOperation (DBObject operation) {
this.operation = operation;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
然后在你的代码中使用:
Aggregation aggregation = newAggregation(
new CutomAggregationOperation(
new BasicDBObject(
"$sample",
new BasicDBObject( "size", 15 )
)
)
);
由于它实现了 AggregationOperation
,因此它与现有的管道操作辅助方法配合得很好。即:
Aggregation aggregation = newAggregation(
// custom pipeline stage
new CutomAggregationOperation(
new BasicDBObject(
"$sample",
new BasicDBObject( "size", 15 )
)
),
// Standard match pipeline stage
match(
Criteria.where("myDate")
.gte(new Date(new Long("949384052490")))
.lte(new Date(new Long("1448257684431")))
)
);
所以,归根结底,一切都只是一个 BSON 对象。这只是一个接口包装器的问题,以便 spring-mongo 中的 class 方法解释结果并正确获取您定义的 BSON 对象。
Blakes Seven 回答正确,但是,我想提供一个更好的 AggregationOperation 实现,它遵循标准 Spring 实施
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.Assert;
public class SampleOperation implements AggregationOperation {
private int size;
public SampleOperation(int size) {
Assert.isTrue(size > 0, " Size must be positive!");
this.size = size;
}
public AggregationOperation setSize(int size) {
Assert.isTrue(size > 0, " Size must be positive!");
this.size = size;
return this;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$sample", context.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
}
}
之后,您可以使用构造函数创建 SampleOperation 对象,或者稍后通过 setSize()
方法更改它的大小,并像往常一样将其应用于 aggregate()
函数。
更新:在 SpringBoot 2.0.0+ 和 Spring Framework 5.0 中:Spring Mongo 删除 DBObject
并替换为 org.bson.Document
因此最后的过去应该更新为:
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return new Document("$sample", aggregationOperationContext.getMappedObject(Criteria.where("size").is(size).getCriteriaObject()));
}
并删除 @Override toDBObject