【问题标题】:Spring boot MongoDb complex querySpring Boot MongoDb 复杂查询
【发布时间】: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,因为我想知道如何连接来自不同集合的两个文档。这只是一个例子。

标签: spring mongodb spring-boot mongodb-query spring-data


【解决方案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。在这种情况下,当您必须使用文档引用时,您可能应该使用聚合框架。
猜你喜欢
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
  • 2019-07-07
  • 2023-04-11
  • 2017-03-28
  • 2021-11-21
相关资源
最近更新 更多