Spring Boot 和 MongoDB,查询嵌套映射的键

Posted

技术标签:

【中文标题】Spring Boot 和 MongoDB,查询嵌套映射的键【英文标题】:Spring Boot & MongoDB, Query nested map for key 【发布时间】:2018-06-24 09:22:11 【问题描述】:

我正在尝试在 MongoDB 中查询在文档的嵌套映射中具有特定键的所有文档


   "_id" : ObjectId("5a5cd9711736c32c45f11adf"),
   "name" : "Test A",
   "userSubscription" : 
      "map" : 
          "1234" : true,
          "999" : true,
      
   

我查询如下:

db.getCollection('myColl').find(  "userSubscription.map" : "1234":true )

它正在工作,但是,它只返回包含单个值“1234”的文档,所以如果“userSubscription.map”包含“1234”“5555 " 查询没有显示任何结果。

我正在使用 Robo3T 来测试查询,并使用 SpringBoot 注释来查询这个, 答案可以在 Spring Boot 注释查询中吗?

Spring Boot 查询示例:

@Query("QUERY : ?0")
List<Person> findByUserSubscription(String key);

** "?0" 是使用第一种方法参数

谢谢!!!

更新:

现在文档看起来像这样:


"_id" : ObjectId("5a5cd9711736c32c45f11adf"),
   "name" : "Test A",    
   "userSubscription" : 
      "1234" : true,
      "3333" : true
    

Robo 3T 查询:db.getCollection('Person').find( "userSubscription.1234": $exists : true )

工作完美!

但是,Spring boot 中的查询看起来像:

@Query("userSubscription.?0 : $exists: true ")

它没有显示任何结果...

什么问题???

【问题讨论】:

【参考方案1】:

将地图建模为array of embedded documents like


  "map" : [
     k: "1234", v: true,
     k: "999", v: true
  ]
      

你可以一键找到

db.myColl.find("userSubscription.map":$elemMatch:  k: "1234", v: true   )

@Query("'userSubscription.map':$elemMatch:  k: ?0, v: true   ")
List<Person> findByUserSubscription(String key);

`

【讨论】:

我无法理解如何从 java 代码中实现这种结构 您必须先运行更新才能移动到新结构,然后才能进行查询。那是你在做什么? Here 就是这样一个例子。如果您不适合更新到新结构,则必须运行聚合。 它不是实时数据库,因此我可以删除该集合。我不明白这种结构在 Java 代码中是如何表示的。 userSubscription 现在是一个包含键和值的 Map 对象数组? 它不是实时数据库,因此我可以删除该集合。我不明白这种结构在 Java 代码中是如何表示的。 userSubscription 现在是一个带有键和值的 Map 对象数组?整个想法不是迭代整个数组,因此我可以使用 map 并且键将是唯一的...... 我同意您的方法,但 mongodb 无法以您的方式查询结构。等效的 mongodb 结构是嵌入文档的数组。所以要在java中建模,你可以使用List&lt;Map&lt;String, Object&gt;&gt;。不需要迭代,因为直接键查找是在服务器端执行的。如果您想保留结构,则必须使用聚合查询,该结构本质上是在查询之前将其转换为聚合管道中的 mongo db 结构【参考方案2】:

在 Spring Data mongodb 中使用 Query 和 Criteria Class 有一个更简单的解决方案。如下:

Query query = new Query();
query.addCriteria(Criteria.where("userSubscription."+key).exists(true));
return mongoTemplate.find(query, YourDocument.class);

【讨论】:

【参考方案3】:

您错过了 @Query 的单引号。

@Query("'userSubscription.?0' : $exists: true ")

【讨论】:

以上是关于Spring Boot 和 MongoDB,查询嵌套映射的键的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 记录 MongoDB 查询

Spring Boot MongoDb 复杂查询

Spring Boot 自定义查询 MongoDB

使用spring boot在mongodb中进行多个搜索查询

spring boot mongodb 模糊查询,开启事务,获取mongoclient 方法

Spring Boot、Spring Security - 防止 MongoDB 的直接 URL 查询