gpt4 book ai didi

java - 使用 Morphia 返回匹配的数组元素

转载 作者:行者123 更新时间:2023-12-02 02:07:22 24 4
gpt4 key购买 nike

我正在寻找一种方法,在提供一些条件后从给定的对象列表中过滤掉所有对象。

例如

A类

@Entity(value = "tbl_A")
public class A {

private String notes;
@Embedded
private List<SampleObject> sampleObject;

....getter and setter ...
}

B 类

@Embedded
public class SampleObject {
private boolean read;
private boolean sentByBot;

... getter and setter ...
}

现在,我只想收集将 sentByBot 参数设置为 trueSampleObject。我正在使用以下方法:

Query<A> queryForA = datastore.find(A.class);
queryForA.field("sampleObject.sentByBot").equal(false).retrievedFields(true, "sampleObject.sentByBot");

上面的代码给了我对象的完整列表,其中sampleObject.sentByBot都有true和false。

我还尝试了过滤方法,即

 queryForA.filter("sampleObject.sentByBot", false).retrievedFields(true, "sampleObject.sentByBot");

但运气不佳。有没有办法只获取那些 sampleObject.sentByBot 设置为 true 的字段?

编辑

实现以下代码后,我得到了:

数据库图像

enter image description here

代码

  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);

输出

"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 }"

最佳答案

如前所述,为了仅返回与给定条件匹配的“多个”数组元素,您需要的是 $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}
]
}

请注意,您需要从 DBObject() 手动构建参数中的 expression(),因为 Morphia 中当前不支持此类操作的“构建器” 。预计 future 的版本将更改为 Document 接口(interface),该接口(interface)在底层 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;
}
}

关于java - 使用 Morphia 返回匹配的数组元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50575792/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com