Java 返回与Morphia匹配的数组元素
我正在寻找一种方法,在提供一些Java 返回与Morphia匹配的数组元素,java,mongodb,mongodb-query,aggregation-framework,morphia,Java,Mongodb,Mongodb Query,Aggregation Framework,Morphia,我正在寻找一种方法,在提供一些条件之后,从给定的对象列表中筛选出所有对象 比如说 甲级 现在,我只想收集SampleObject,它的sentbybbot参数设置为true。我采用以下方法: Query<A> queryForA = datastore.find(A.class); queryForA.field("sampleObject.sentByBot").equal(false).retrievedFields(true, "sampleObject.sentByBot")
条件之后,从给定的对象列表中筛选出所有对象
比如说
甲级
现在,我只想收集SampleObject
,它的sentbybbot
参数设置为true
。我采用以下方法:
Query<A> queryForA = datastore.find(A.class);
queryForA.field("sampleObject.sentByBot").equal(false).retrievedFields(true, "sampleObject.sentByBot");
但是没有运气。有没有办法只获取那些将sampleObject.Sentbybbot设置为true的字段
编辑
在实现以下代码后,我得到了以下结果:
数据库映像
代码
如前所述,为了只返回与给定条件匹配的“多个”数组元素,您需要的是投影中的聚合管道操作符。为了向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}
]
}
请注意,您需要从DBObject()
手动生成expression()
in参数,因为Morphia中不支持这种类型的操作。预计未来的版本将更改为文档
接口,该接口在底层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;
}
}
package com.snakier.example;
导入com.mongodb.AggregationOptions;
导入com.mongodb.BasicDBObject;
导入com.mongodb.MongoClient;
导入org.bson.types.ObjectId;
导入org.mongodb.morphia.Datastore;
导入org.mongodb.morphia.morphia;
导入org.mongodb.morphia.aggregation.AggregationPipeline;
导入org.mongodb.morphia.aggregation.Projection;
导入org.mongodb.morphia.annotations.Embedded;
导入org.mongodb.morphia.annotations.Entity;
导入org.mongodb.morphia.annotations.Id;
导入java.util.array;
导入java.util.Iterator;
导入java.util.List;
导入静态org.mongodb.morphia.aggregation.Projection.*;
公共类应用程序{
公共静态void main(字符串[]args){
最终Morphia Morphia=新Morphia();
mapPackage(“com.snakier.example”);
final Datastore Datastore=morphia.createDatastore(新的MongoClient(),“示例”);
//干净示例数据库
datastore.getDB().getCollection(“示例”).drop();
//创建一些数据
最终A第一=新A(“某物”、“其他”);
最后一秒=新的A(“另一个”,“事物”);
最终SampleObject firstSample=新的SampleObject(“一”,假,真);
最终SampleObject secondSample=新的SampleObject(“两个”,假,假);
最终SampleObject thirdSample=新的SampleObject(“三”,真,真);
最终SampleObject fourthSample=新的SampleObject(“四”,真,假);
first.setSampleObjects(Arrays.asList(firstSample、secondSample、thirdSample));
datastore.save(第一);
其次,设置采样对象(Arrays.asList(fourthSample));
数据存储。保存(秒);
AggregationOptions=AggregationOptions.builder()
.outputMode(聚合选项.outputMode.CURSOR)
.build();
//System.out.println(options.toString());
投影过滤器投影=投影(
“采样对象”,
表情(
“$filter”,
新的BasicDBObject(“输入”,“$sampleObjects”)
.append(“cond”,新的BasicDBObject($eq),Arrays.asList($this.sentbybbot),true)))
)
);
AggregationPipeline=datastore.createAggregation(A.class)
.match(datastore.createQuery(A.class).filter(“sampleObjects.sentbybbot”,true))
.项目(
投影(“fieldA”),
投影(“字段B”),
过滤喷射
);
迭代器游标=pipeline.aggregate(A.class,options);
while(cursor.hasNext()){
System.out.println(morphia.toDBObject(cursor.next());
}
}
}
@实体(value=“示例”)
甲级{
@身份证
私有ObjectId;
私有字符串字段a;
私有字符串字段b;
@嵌入
私有列表样本对象;
公共A(){
}
公共A(字符串字段A、字符串字段B){
this.fieldA=fieldA;
this.fieldB=fieldB;
}
public void设置采样对象(列出采样对象){
this.sampleObjects=sampleObjects;
}
公共列表getSampleObjects(){
返回样本对象;
}
公共ObjectId getId(){
返回id;
}
公共字符串getFieldA(){
返回场A;
}
公共无效集合字段A(字符串字段A){
this.fieldA=fieldA;
}
公共无效集合字段B(字符串字段B){
this.fieldB=fieldB;
}
公共字符串getFieldB(){
返回字段B;
}
}
@嵌入
类采样对象{
私有字符串名称;
私有布尔读取;
私有布尔Sentbot;
公共样本对象(){
}
公共SampleObject(字符串名称、布尔读取、布尔Sentbybbot){
this.name=名称;
this.read=read;
this.sentByBot=sentByBot;
}
公共字符串getName(){
返回名称;
}
公共布尔值isRead(){
返回读取;
}
公共布尔值isSentByBot(){
返回sentByBot;
}
}
如上所示,您想要的实际上是由聚合运算符实现的。以这种方式“修改文档”不是常规查询表达式的工作,您最多只能使用常规查询返回。您需要为此构造聚合语句。@NeilLunn我如何在morphia
中实现$filter
?感谢您的解释和示例,但我得到了这个错误$filter仅支持对象作为其参数“
在迭代器游标=pipeline.aggregate(A.clas
"Command failed with error 28646: '$filter only supports an object as its argument'. The full response is { \"ok\" : 0.0, \"errmsg\" : \"$filter only supports an object as its argument\", \"code\" : 28646 }"
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}
]
}
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;
}
}