我正在寻找一种方法,在提供一些List of Object
后过滤掉给定conditions
中的所有对象。
例如
@Entity(value = "tbl_A")
public class A {
private String notes;
@Embedded
private List<SampleObject> sampleObject;
....getter and setter ...
}
@Embedded
public class SampleObject {
private boolean read;
private boolean sentByBot;
... getter and setter ...
}
现在,我只想收集SampleObject
参数设置为sentByBot
的{{1}}。我正在使用以下方法:
true
上面的代码为我提供了Query<A> queryForA = datastore.find(A.class);
queryForA.field("sampleObject.sentByBot").equal(false).retrievedFields(true, "sampleObject.sentByBot");
的完整列表,其中objects
都是真假。
我也试过sampleObject.sentByBot
方法,即
filter
但没有运气。有没有办法让这些字段只有 queryForA.filter("sampleObject.sentByBot", false).retrievedFields(true, "sampleObject.sentByBot");
设置为真?
实现以下代码后,我得到了这个:
sampleObject.sentByBot
AggregationOptions options = AggregationOptions.builder()
.outputMode(AggregationOptions.OutputMode.CURSOR)
.build();
//System.out.println(options.toString());
Projection filterProjection = Projection.projection(
"sampleObjects",
Projection.expression(
"$filter",
new BasicDBObject("input","$sampleObjects")
.append("cond",new BasicDBObject("$eq", Arrays.asList("$$this.sentByBot",true)))
)
);
AggregationPipeline pipeline = datastore.createAggregation(A.class)
.match(datastore.createQuery(A.class).filter("sampleObjects.sentByBot", true))
.project(
Projection.projection("fieldA"),
Projection.projection("fieldB"),
filterProjection
);
Iterator<A> cursor = pipeline.aggregate(A.class, options);
答案 0 :(得分:1)
如前所述,你想要的只是返回&#34;多个&#34;匹配给定条件的数组元素是投影中的$filter
聚合管道运算符。为了与Morphia发布这样的聚合语句,你需要这样的东西:
Projection filterProjection = projection(
"sampleObjects",
expression(
"$filter",
new BasicDBObject("input","$sampleObjects")
.append("cond",new BasicDBObject("$eq", Arrays.asList("$$this.sentByBot",true)))
)
);
AggregationPipeline pipeline = datastore.createAggregation(A.class)
.match(datastore.createQuery(A.class).filter("sampleObjects.sentByBot", true))
.project(
projection("fieldA"),
projection("fieldB"),
filterProjection
);
将管道发布到服务器:
[
{ "$match" : { "sampleObjects.sentByBot" : true } },
{ "$project" : {
"fieldA" : 1,
"fieldB" : 1,
"sampleObjects" : {
"$filter" : {
"input" : "$sampleObjects",
"cond" : { "$eq" : [ "$$this.sentByBot", true ] }
}
}
}}
]
并且只返回匹配条件中的数组元素:
{
"className" : "com.snakier.example.A" ,
"_id" : { "$oid" : "5b0ce52c6a6bfa50084c53aa"} ,
"fieldA" : "something" ,
"fieldB" : "else" ,
"sampleObjects" : [
{ "name" : "one" , "read" : false , "sentByBot" : true} ,
{ "name" : "three" , "read" : true , "sentByBot" : true}
]
}
请注意,您需要从expression()
手动构建参数DBObject()
,因为当前没有#34;构建器&#34; Morphia支持这种类型的操作。预计将来的版本将更改为Document
接口,该接口已在基础Java驱动程序中标准化了一段时间。
作为完整的示例列表:
package com.snakier.example;
import com.mongodb.AggregationOptions;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import org.bson.types.ObjectId;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
import org.mongodb.morphia.aggregation.AggregationPipeline;
import org.mongodb.morphia.aggregation.Projection;
import org.mongodb.morphia.annotations.Embedded;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import static org.mongodb.morphia.aggregation.Projection.*;
public class Application {
public static void main(String[] args) {
final Morphia morphia = new Morphia();
morphia.mapPackage("com.snakier.example");
final Datastore datastore = morphia.createDatastore(new MongoClient(),"example");
// Clean example database
datastore.getDB().getCollection("example").drop();
// Create some data
final A first = new A("something","else");
final A second = new A("another","thing");
final SampleObject firstSample = new SampleObject("one", false, true);
final SampleObject secondSample = new SampleObject("two", false, false);
final SampleObject thirdSample = new SampleObject("three", true,true);
final SampleObject fourthSample = new SampleObject("four", true, false);
first.setSampleObjects(Arrays.asList(firstSample,secondSample,thirdSample));
datastore.save(first);
second.setSampleObjects(Arrays.asList(fourthSample));
datastore.save(second);
AggregationOptions options = AggregationOptions.builder()
.outputMode(AggregationOptions.OutputMode.CURSOR)
.build();
//System.out.println(options.toString());
Projection filterProjection = projection(
"sampleObjects",
expression(
"$filter",
new BasicDBObject("input","$sampleObjects")
.append("cond",new BasicDBObject("$eq", Arrays.asList("$$this.sentByBot",true)))
)
);
AggregationPipeline pipeline = datastore.createAggregation(A.class)
.match(datastore.createQuery(A.class).filter("sampleObjects.sentByBot", true))
.project(
projection("fieldA"),
projection("fieldB"),
filterProjection
);
Iterator<A> cursor = pipeline.aggregate(A.class, options);
while (cursor.hasNext()) {
System.out.println(morphia.toDBObject(cursor.next()));
}
}
}
@Entity(value = "example")
class A {
@Id
private ObjectId id;
private String fieldA;
private String fieldB;
@Embedded
private List<SampleObject> sampleObjects;
public A() {
}
public A(String fieldA, String fieldB) {
this.fieldA = fieldA;
this.fieldB = fieldB;
}
public void setSampleObjects(List<SampleObject> sampleObjects) {
this.sampleObjects = sampleObjects;
}
public List<SampleObject> getSampleObjects() {
return sampleObjects;
}
public ObjectId getId() {
return id;
}
public String getFieldA() {
return fieldA;
}
public void setFieldA(String fieldA) {
this.fieldA = fieldA;
}
public void setFieldB(String fieldB) {
this.fieldB = fieldB;
}
public String getFieldB() {
return fieldB;
}
}
@Embedded
class SampleObject {
private String name;
private boolean read;
private boolean sentByBot;
public SampleObject() {
}
public SampleObject(String name, boolean read, boolean sentByBot) {
this.name = name;
this.read = read;
this.sentByBot = sentByBot;
}
public String getName() {
return name;
}
public boolean isRead() {
return read;
}
public boolean isSentByBot() {
return sentByBot;
}
}