Java 根据字段的存在,使用MongoDB中的Spring投射一个布尔值

Java 根据字段的存在,使用MongoDB中的Spring投射一个布尔值,java,spring,mongodb,Java,Spring,Mongodb,我需要根据MongoDB with Spring Framework中文档中某个字段的存在情况投射一个布尔值 假设我的Mongo数据库中有文档。它们的结构如下所示(testedField可能不存在): 或者像这样: { "_id": ObjectId("some object ID"), "field1": "some value", "field2": "another value" } 我还有一个数据类MyClass: @AllArgsConstructor @Ge

我需要根据MongoDB with Spring Framework中文档中某个字段的存在情况投射一个布尔值

假设我的Mongo数据库中有文档。它们的结构如下所示(testedField可能不存在):

或者像这样:

{
    "_id": ObjectId("some object ID"),
    "field1": "some value",
    "field2": "another value"
}
我还有一个数据类MyClass:

@AllArgsConstructor
@Getter
public class MyClass {
    private String field1;
    private String field2;
    private boolean myBoolVal;
}
在我的DAO中,有一个方法将其字段的值投影到类:

public List<MyClass> findThings(Collection<ObjectId> ids) {
    Criteria criteria = where(ID).in(ids);
    Aggregation matchAndProject = newAggregation(
            match(criteria),
            project("field1", "field2")
                    .and("testedField").ne(null).as("myBoolVal"));
    return mongoTemplate.aggregate(matchAndProject, "my_collection", MyClass.class).getMappedResults();
}
公共列表查找内容(集合ID){
标准=其中(ID).in(ID);
聚合匹配项目=newAggregation(
匹配(标准),
项目(“现场1”、“现场2”)
。和(“testedField”).ne(null).as(“myBoolVal”);
返回mongoTemplate.aggregate(matchAndProject,“我的收藏”,MyClass.class).getMappedResults();
}
如果testedField存在,则在myBoolVal字段中设置
true
,如果不存在,则在
false
字段中设置

但是上面的代码抛出了
IllegalArgumentException(“值不能为null!”)


有办法让它工作吗?

为什么不
Boolean
true
如果字段存在,
false
null
如果不存在

但是在您的例子中,字段
myBoolVal
任何内容都等于
false
。有一件事-你的场是最终的,你不能对它们进行任何操作。。。将实体字段设置为
final
是不正确的


最后一件事:你用弹簧吗?它有一个用于mongodb的完美库,使用mongodb与jpa功能非常相似。

使用条件投影

public List<MyClass> findThings(Collection<ObjectId> ids) {

    Cond condition = ConditionalOperators.when(Criteria.where("testedField")
        .exists(true))
        .then(true)
        .otherwise(false)
    ;
    Criteria criteria = where(ID).in(ids);
    Aggregation matchAndProject = newAggregation(
            match(criteria),
            project("field1", "field2")
                    and(condition).as("myBoolVal"));
    return mongoTemplate.aggregate(matchAndProject, "my_collection", MyClass.class).getMappedResults();
}
公共列表查找内容(集合ID){
Cond condition=条件运算符.when(条件.where(“testedField”)
.存在(真实))
.那么(对)
。否则(错)
;
标准=其中(ID).in(ID);
聚合匹配项目=newAggregation(
匹配(标准),
项目(“现场1”、“现场2”)
和(条件)。如(“myBoolVal”);
返回mongoTemplate.aggregate(matchAndProject,“我的收藏”,MyClass.class).getMappedResults();
}

我找到了解决方案:只要在不存在
的情况下(“字段名”)
使用
就足够了(
为(null)

public List<MyClass> findThings(Collection<ObjectId> ids) {
    Criteria criteria = where(ID).in(ids);
    Aggregation matchAndProject = newAggregation(
            match(criteria),
            project("field1", "field2")
                    .and(ConditionalOperators.when("testedField")
                        .then(true)
                        .otherwise(false))
                    .as("myBoolVal"));
    return mongoTemplate.aggregate(matchAndProject, "my_collection", MyClass.class).getMappedResults();
}
公共列表查找内容(集合ID){
标准=其中(ID).in(ID);
聚合匹配项目=newAggregation(
匹配(标准),
项目(“现场1”、“现场2”)
.和(条件运算符。何时(“测试字段”)
.那么(对)
。否则(错误))
.as(“myBoolVal”);
返回mongoTemplate.aggregate(matchAndProject,“我的收藏”,MyClass.class).getMappedResults();
}

问题在于聚合本身:它不允许在
ne()
方法中使用
null
。这些方法来自Spring的
org.springframework.data.mongodb.core
包。在这种情况下,为什么您的实体类没有用
@Document
@Field
,no
@Id
注释?如果要处理实体之类的对象,请将其替换为实体),好的,但这仍然无法解决问题。它最终导致:
com.mongodb.MongoCommandException:Command失败,错误为168(InvalidPipelineOperator):“无法识别的表达式“$exists”
替换此代码并尝试Cond condition=ConditionalOperators.when(Criteria.where(“testedField”)。为(null))。然后为(false)。否则为(true);两个答案之间有很大的区别,如果你更加注意的话,这些答案可以让你在不使用MongoCommandException的情况下使用查询。方法
exists()
导致上述异常,因此应避免使用它。这是你所指答案的评论部分。
public List<MyClass> findThings(Collection<ObjectId> ids) {
    Criteria criteria = where(ID).in(ids);
    Aggregation matchAndProject = newAggregation(
            match(criteria),
            project("field1", "field2")
                    .and(ConditionalOperators.when("testedField")
                        .then(true)
                        .otherwise(false))
                    .as("myBoolVal"));
    return mongoTemplate.aggregate(matchAndProject, "my_collection", MyClass.class).getMappedResults();
}