【问题标题】:MongoDB java driver passing undefined as valueMongoDB java驱动程序将未定义作为值传递
【发布时间】:2021-05-24 01:34:16
【问题描述】:

我有下面的 mongoDB 聚合,它在我的 mongodb 集合项中过滤测试数组。

样本集合项:{,...tests:[ {} , {"someField":"yesIamHere"} ] }

以下查询运行良好,仅返回包含 someField 的测试集合

db.getCollection('yourcollection')
.aggregate([
{"$match": {"tests.someField": {"$exists": true}}},
{ $project:{"tests": {"$filter": {"input": "$tests", "as": "item", 
    "cond": {"$ne": ["$$item.someField", undefined]}}}}
},
])

然而,

虽然使用 java BasicDBObject 将 "undefined" 作为字符串而不是 JS undefined

    BasicDBObject projectionFilterInput=new BasicDBObject("input","$tests")
        .append("as", "item")
        .append("cond",new BasicDBObject("$ne", Arrays.asList("$$item.someField","undefined")));

因此,这解释了 "cond": {"$ne": ["$$item.vidaptorCode", "undefined"]}}}} "undefined" 而不是 undefined。因此,这不会按预期过滤项目。

在 mongodb java 驱动程序库中是否为这个特定的undefined 值定义了任何常量?这是主要问题。

谁好奇...

为什么我不使用 ODM?

实际上我们确实使用 Spring Data for MongoDB,但它不支持这种聚合cond。

    MatchOperation matchStage = Aggregation.match(new Criteria("tests.someField").exists(true));        
    ProjectionOperation projection = Aggregation.project("tests");  

Aggregation aggregation 
      = Aggregation.newAggregation(matchStage, projection);
    
    AggregationResults<LabConfiguration> output 
      = mongoTemplate.aggregate(aggregation, "yourcollection", YourClass.class);

Morphia ODM

我喜欢 Morphia 流畅的语法,但是它们使用的注释与 Spring Data Mongo 不同,并且其依赖的 MongoDB 库也不同。简而言之,两个 ODM 不能一起工作。 最大的问题是你需要实现 BasicDAO&lt;C,K&gt; 的存储库实现,它不是很实用,它是面向 mongo 的,Spring Data Mongo 在 MongoRepository&lt;C,K&gt; 方面做得很好

    Projections filterProjection = projection(
            "tests",
            expression(
                    "$filter",
                    new BasicDBObject("input","$tests")
                    .append("as", "item")
                    .append("cond",new BasicDBObject("$ne", Arrays.asList("$$item.someField","undefined")))
            )
    );

因此,我最终使用了 Mongo 驱动程序基本语法来解决这个问题,这就是为什么我需要将 undefined 传递给 BasiDBObject 而不是作为双引号覆盖的字符串。

我也愿意听取您的总体建议。我们现在拥有的是QueryDSL 和Spring Data for MongoDB。

【问题讨论】:

  • 您不能在聚合的$filter 操作中检查“未定义” - 使用$ifNull 聚合运算符构造cond 的条件。
  • @prasad_ 感谢您的评论,我认为 ifNull 不是一回事。我们在某些文档中根本没有该字段。未定义检查适用于数据库工具,必须有办法
  • 嗨@DavutGürbüz,Java 使用原始类型并且无法理解未定义的javascript,它总是将其作为字符串值。我同意@prasad 的建议,官方文档指出$ifNull covers the undefined value as well as missing field。请查看docs.mongodb.com/manual/reference/operator/aggregation/ifNull
  • 如果你一定不想使用上面的建议,总是有这个 hack 可以将 json 直接转换为 DBObject,但是它更多的是 hack 而不是实现,并且不能保证它会工作百分之几。检查https://stackoverflow.com/questions/16333549/converting-json-structure-to-basicdbobject/48234498
  • 嗨@RahulKumar,谢谢。真的行。我期待像 $ifNotNull 之类的东西 :)

标签: java mongodb aggregation-framework


【解决方案1】:

正如其他人在我的 OP 中评论的那样,替代方法是使用 $ifNull。

实际上,我期待使用{extists:true},但它不是一个有效的aggregation cond 运算符或类似$ifNotNull 的东西会很好,但它也可以通过$ifNull 实现。

如您所知,投影适用于 0 和 1,即{name:1,_id:0}

所以,我决定在$ifNull 时返回0 并且成功了!

Java MongoDB核心驱动方式

BasicDBObject projectionFilterInput=new BasicDBObject("input","$tests")
.append("as", "item")
.append("cond",new BasicDBObject("$ifNull",Arrays.asList("$$item.someField",0)));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-13
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 2013-08-16
    • 1970-01-01
    相关资源
    最近更新 更多