Spring Boot MongoDb 复杂查询

Posted

技术标签:

【中文标题】Spring Boot MongoDb 复杂查询【英文标题】:Spring boot MongoDb complex query 【发布时间】:2019-10-05 15:32:18 【问题描述】:

我一直在学习自己在 Spring Boot 中的 MongoDB 实现。 但是,我遇到了复杂查询的问题。

我找不到任何正确的解决方案来解决如何从 Spring boot 实现对 MongoDB 的复杂查询。

我正在使用MongoRepository接口实现查询数据库。

假设我有三个集合:

Person - 1 Person 可以拥有许多 Pet。 宠物 - 1 只宠物可以拥有 1 个 PetToy 和 1 个拥有他的人。 PetToy - 1 个 PetToy 可以属于 1 个 Pet。

POJO 类如下

我想达到什么目的?

我想查询,它会返回一个 Person,他的宠物有一个玩具 (PetToy),名字叫“Teddy”。

我无法找到一种方法来做到这一点。此外,甚至使用如此复杂的查询是最佳实践,还是在 MongoDB 中编写更多的小查询更好?

POJO:

@Document
@Data
@ToString
public class Person 

    @Id
    private String id;

    private String firstname;

    private String lastname;

    private int age;

    @DBRef
    private Pet pet;


@Document
@Data
@ToString
public class Pet 

    @Id
    private String id;

    private String name;

    private int age;

    @DBRef
    private List<PetToy> toys;


@Document
@Data
@ToString
public class PetToy 

    @Id
    private String id;

    private String name;

我尝试过使用 MongoRepositories;但是,我无法进行复杂的查询。

如何从 Spring Boot 向 MongoDB 写入这样的查询?

非常感谢您。

【问题讨论】:

在 Person->Pet 和 Pet->Pet Toys 之间的关系中使用 @DBRef 是否有任何理由代替嵌入属性? 我使用了@DBRef,因为我想知道如何连接来自不同集合的两个文档。这只是一个例子。 【参考方案1】:

如果可以使用嵌入属性,类模型应该是:

@Document
@Data
@Builder
public class Person 

    @Id
    private String id;

    private String firstName;

    private String lastName;

    private int age;

    private List<Pet> pets;

@Data
@Builder
public class Pet 

    private String name;

    private int age;

    private List<PetToy> toys;

@Data
@Builder
public class PetToy 

    private String name;

具有实现您想要的方法的存储库:

public interface PersonRepository extends MongoRepository<Person, String> 
    List<Person> getByPetsToysName(String name);

getByPetsToysName 方法基本上在 Person 的属性 Person->pets->toys->name 之间导航。更多信息here.

一个例子

@Configuration
@EnableMongoRepositories
public class TestMongo implements CommandLineRunner 

  private final PersonRepository repository;

  public TestMongo(PersonRepository repository) 
    this.repository = repository;
  

  @Override
  public void run(String... args) throws Exception 

    repository.save(Person.builder()
      .firstName("John")
      .lastName("Doe")
      .age(20)
      .pets(Stream.of(Pet.builder()
        .name("Ursa")
        .age(1)
        .toys(Stream.of(PetToy.builder()
          .name("Teddy")
          .build())
          .collect(Collectors.toList()))
        .build())
        .collect(Collectors.toList()))
      .build());

    repository.save(Person.builder()
      .firstName("Phillip")
      .lastName("Larson")
      .age(21)
      .pets(Stream.of(Pet.builder()
        .name("Bella")
        .age(5)
        .toys(Stream.of(PetToy.builder()
          .name("Lolo")
          .build())
          .collect(Collectors.toList()))
        .build())
        .collect(Collectors.toList()))
      .build());

    List<Person> persons = repository.getByPetsToysName("Teddy");
    System.out.println(persons.size());
    List<Person> persons1 = repository.getByPetsToysName("Lolo");
    System.out.println(persons1.size());
  

日志:

find using query:  "pets.toys.name" : "Teddy"  fields: Document for class: class Person in collection: person

如果您想要更复杂的查询,可以查看Spring Data MongoDB docs。

【讨论】:

谢谢,我知道如果可能的话,最好使用 Embedded Documents。在这种情况下,当您必须使用文档引用时,您可能应该使用聚合框架。

以上是关于Spring Boot MongoDb 复杂查询的主要内容,如果未能解决你的问题,请参考以下文章

Spring-boot数据mongoDB查询嵌套列表

使用 Spring Boot 记录 MongoDB 查询

Spring Boot 自定义查询 MongoDB

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

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

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