MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Hướng dẫn truy vấn trong dữ liệu mùa xuân MongoDB

1. Tổng quan

Hướng dẫn này sẽ tập trung vào việc xây dựng các loại truy vấn khác nhau trong Spring Data MongoDB .

Chúng tôi sẽ xem xét truy vấn tài liệu bằng Truy vấn Tiêu chí các lớp, phương thức truy vấn được tạo tự động, truy vấn JSON và QueryDSL.

Để biết cách thiết lập Maven, hãy xem bài viết giới thiệu của chúng tôi.

2. Truy vấn tài liệu

Một trong những cách phổ biến hơn để truy vấn MongoDB với Dữ liệu mùa xuân là sử dụng Truy vấn Tiêu chí các lớp, phản ánh rất chặt chẽ các toán tử gốc.

2.1.

Đây chỉ đơn giản là một tiêu chí sử dụng bình đẳng. Hãy xem nó hoạt động như thế nào.

Trong ví dụ sau, chúng tôi sẽ tìm kiếm những người dùng có tên là Eric .

Hãy xem cơ sở dữ liệu của chúng tôi:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 55
    }
}

Bây giờ hãy xem mã truy vấn:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eric"));
List<User> users = mongoTemplate.find(query, User.class);

Như mong đợi, logic này trả về:

{
    "_id" : ObjectId("55c0e5e5511f0a164a581907"),
    "_class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.2. Regex

Một loại truy vấn linh hoạt và mạnh mẽ hơn là regex. Điều này tạo ra một tiêu chí bằng cách sử dụng MongoDB $ regex trả về tất cả các bản ghi phù hợp với regex cho trường này.

Nó hoạt động tương tự như startedWith endingWith hoạt động.

Trong ví dụ này, chúng tôi sẽ tìm kiếm tất cả người dùng có tên bắt đầu bằng A .

Đây là trạng thái của cơ sở dữ liệu:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }
]

Bây giờ hãy tạo truy vấn:

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("^A"));
List<User> users = mongoTemplate.find(query,User.class);

Thao tác này chạy và trả về 2 bản ghi:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }
]

Đây là một ví dụ nhanh khác, lần này tìm kiếm tất cả người dùng có tên kết thúc bằng c :

Query query = new Query();
query.addCriteria(Criteria.where("name").regex("c$"));
List<User> users = mongoTemplate.find(query, User.class);

Vì vậy, kết quả sẽ là:

{
    "_id" : ObjectId("55c0e5e5511f0a164a581907"),
    "_class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.3. Lt gt

Các toán tử này tạo tiêu chí bằng cách sử dụng $ lt (nhỏ hơn) và $ gt (lớn hơn) toán tử.

Hãy lấy một ví dụ nhanh mà chúng tôi đang tìm kiếm tất cả người dùng trong độ tuổi từ 20 đến 50.

Cơ sở dữ liệu là:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 55
    }
}

Mã truy vấn:

Query query = new Query();
query.addCriteria(Criteria.where("age").lt(50).gt(20));
List<User> users = mongoTemplate.find(query,User.class);

Và kết quả cho tất cả người dùng có độ tuổi lớn hơn 20 và dưới 50:

{
    "_id" : ObjectId("55c0e5e5511f0a164a581907"),
    "_class" : "org.baeldung.model.User",
    "name" : "Eric",
    "age" : 45
}

2.4. Sắp xếp

Sắp xếp được sử dụng để chỉ định thứ tự sắp xếp cho các kết quả.

Ví dụ dưới đây trả về tất cả người dùng được sắp xếp theo độ tuổi theo thứ tự tăng dần.

Đầu tiên, đây là dữ liệu hiện có:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }
]

Sau khi thực hiện sắp xếp :

Query query = new Query();
query.with(Sort.by(Sort.Direction.ASC, "age"));
List<User> users = mongoTemplate.find(query,User.class);

Và đây là kết quả của truy vấn, được sắp xếp độc đáo theo tuổi :

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    }
]

2.5. Pagable

Hãy xem một ví dụ nhanh bằng cách sử dụng phân trang.

Đây là trạng thái của cơ sở dữ liệu:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }
]

Bây giờ đây là logic truy vấn, chỉ cần yêu cầu một trang có kích thước 2:

final Pageable pageableRequest = PageRequest.of(0, 2);
Query query = new Query();
query.with(pageableRequest);

Và kết quả, 2 tài liệu, như mong đợi:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581907"),
        "_class" : "org.baeldung.model.User",
        "name" : "Eric",
        "age" : 45
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    }
]

3. Phương thức truy vấn đã tạo

Bây giờ chúng ta hãy khám phá loại truy vấn phổ biến hơn mà Spring Data thường cung cấp, các truy vấn được tạo tự động ngoài tên phương thức.

Điều duy nhất chúng ta cần làm để tận dụng các loại truy vấn này là khai báo phương thức trên giao diện kho lưu trữ:

public interface UserRepository 
  extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {
    ...
}

3.1. FindByX

Chúng ta sẽ bắt đầu đơn giản, bằng cách khám phá loại truy vấn findBy. Trong trường hợp này, chúng tôi sẽ sử dụng tìm theo tên:

List<User> findByName(String name);

Cũng giống như trong phần trước, 2.1, truy vấn sẽ có cùng kết quả, tìm tất cả người dùng có tên đã cho:

List<User> users = userRepository.findByName("Eric");

3.2. Bắt đầu với endingWith

Trong phần 2.2, chúng tôi đã khám phá một regex truy vấn dựa trên. Bắt đầu và kết thúc tất nhiên là kém mạnh mẽ hơn, nhưng vẫn khá hữu ích, đặc biệt nếu chúng ta không thực sự phải triển khai chúng.

Dưới đây là một ví dụ nhanh về các hoạt động sẽ trông như thế nào:

List<User> findByNameStartingWith(String regexp);
List<User> findByNameEndingWith(String regexp);

Tất nhiên, ví dụ thực sự sử dụng điều này sẽ rất đơn giản:

List<User> users = userRepository.findByNameStartingWith("A");
List<User> users = userRepository.findByNameEndingWith("c");

Và kết quả hoàn toàn giống nhau.

3.3. Giữa

Tương tự như phần 2.3, điều này sẽ trả về tất cả người dùng có độ tuổi từ ageGT ageLT:

List<User> findByAgeBetween(int ageGT, int ageLT);

Việc gọi phương thức sẽ dẫn đến việc tìm thấy chính xác các tài liệu giống nhau:

List<User> users = userRepository.findByAgeBetween(20, 50);

3.4. Thích OrderBy

Chúng ta hãy xem xét một ví dụ nâng cao hơn lần này, kết hợp hai loại công cụ sửa đổi cho truy vấn đã tạo.

Chúng tôi sẽ tìm kiếm tất cả người dùng có tên chứa chữ cái A, và chúng tôi cũng sẽ sắp xếp kết quả theo độ tuổi, theo thứ tự tăng dần:

List<User> users = userRepository.findByNameLikeOrderByAgeAsc("A");

Đối với cơ sở dữ liệu chúng tôi đã sử dụng trong phần 2.4, kết quả sẽ là:

[
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581908"),
        "_class" : "org.baeldung.model.User",
        "name" : "Antony",
        "age" : 33
    },
    {
        "_id" : ObjectId("55c0e5e5511f0a164a581909"),
        "_class" : "org.baeldung.model.User",
        "name" : "Alice",
        "age" : 35
    }
]

4. Phương thức truy vấn JSON

Nếu chúng tôi không thể biểu diễn một truy vấn với sự trợ giúp của tên phương thức hoặc tiêu chí, chúng tôi có thể thực hiện điều gì đó ở mức thấp hơn, sử dụng @Query chú thích .

Với chú thích này, chúng tôi có thể chỉ định một truy vấn thô dưới dạng chuỗi truy vấn Mongo JSON.

4.1. FindBy

Hãy bắt đầu đơn giản và xem xét cách chúng tôi đại diện cho a find by loại phương pháp đầu tiên:

@Query("{ 'name' : ?0 }")
List<User> findUsersByName(String name);

Phương thức này sẽ trả về người dùng theo tên. Trình giữ chỗ ? 0 tham chiếu đến tham số đầu tiên của phương thức.

List<User> users = userRepository.findUsersByName("Eric");

4.2. $ regex

Chúng tôi cũng có thể xem xét truy vấn theo hướng regex, tất nhiên cái nào tạo ra kết quả tương tự như trong phần 2.2 và 3.2:

@Query("{ 'name' : { $regex: ?0 } }")
List<User> findUsersByRegexpName(String regexp);

Cách sử dụng cũng hoàn toàn giống nhau:

List<User> users = userRepository.findUsersByRegexpName("^A");
List<User> users = userRepository.findUsersByRegexpName("c$");

4.3. $ lt $ gt

Bây giờ, hãy triển khai lt và gt truy vấn:

@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")
List<User> findUsersByAgeBetween(int ageGT, int ageLT);

Bây giờ phương thức có 2 tham số, chúng tôi đang tham chiếu từng tham số này theo chỉ mục trong truy vấn thô, ? 0 ? 1:

List<User> users = userRepository.findUsersByAgeBetween(20, 50);

5. Truy vấnDSL Truy vấn

MongoRepository có hỗ trợ tốt cho dự án QueryDSL, vì vậy chúng tôi cũng có thể tận dụng API tốt, an toàn về kiểu chữ đó tại đây.

5.1. Sự phụ thuộc của Maven

Đầu tiên, hãy đảm bảo rằng chúng ta có các phụ thuộc Maven chính xác được xác định trong pom:

<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-mongodb</artifactId>
    <version>4.3.1</version>
</dependency>
<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <version>4.3.1</version>
</dependency>

5.2. Q -các lớp

QueryDSL đã sử dụng các lớp Q để tạo các truy vấn, nhưng vì chúng tôi không thực sự muốn tạo các truy vấn này theo cách thủ công, chúng tôi cần tạo chúng bằng cách nào đó.

Chúng tôi sẽ sử dụng apt-maven-plugin để làm điều đó:

<plugin>    
    <groupId>com.mysema.maven</groupId>
    <artifactId>apt-maven-plugin</artifactId>
    <version>1.1.3</version>
    <executions>
        <execution>
            <goals>
                <goal>process</goal>
            </goals>
            <configuration>
                <outputDirectory>target/generated-sources/java</outputDirectory>
                <processor>
                  org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
                </processor>
            </configuration>
        </execution>
     </executions>
</plugin>

Hãy xem xét Người dùng , tập trung đặc biệt vào @QueryEntity chú thích:

@QueryEntity 
@Document
public class User {
 
    @Id
    private String id;
    private String name;
    private Integer age;
 
    // standard getters and setters
}

Sau khi chạy quá trình mục tiêu của vòng đời Maven (hoặc bất kỳ mục tiêu nào khác sau vòng đời đó), plugin apt sẽ tạo các lớp mới trong target / created-sources / java / {your package structure} :

/**
 * QUser is a Querydsl query type for User
 */
@Generated("com.mysema.query.codegen.EntitySerializer")
public class QUser extends EntityPathBase<User> {

    private static final long serialVersionUID = ...;

    public static final QUser user = new QUser("user");

    public final NumberPath<Integer> age = createNumber("age", Integer.class);

    public final StringPath id = createString("id");

    public final StringPath name = createString("name");

    public QUser(String variable) {
        super(User.class, forVariable(variable));
    }

    public QUser(Path<? extends User> path) {
        super(path.getType(), path.getMetadata());
    }

    public QUser(PathMetadata<?> metadata) {
        super(User.class, metadata);
    }
}

Chính vì lớp này mà chúng ta không cần tạo các truy vấn của mình.

Lưu ý thêm, nếu chúng tôi đang sử dụng Eclipse, việc giới thiệu plugin này sẽ tạo ra cảnh báo sau trong pom:

The Maven cài đặt hoạt động tốt và QUser lớp được tạo, nhưng một plugin được đánh dấu trong pom.

Cách khắc phục nhanh chóng là trỏ đến JDK theo cách thủ công trong eclipse.ini :

...
-vm
{path_to_jdk}\jdk{your_version}\bin\javaw.exe

5.3. Kho lưu trữ mới

Bây giờ, chúng tôi cần thực sự bật hỗ trợ QueryDSL trong kho lưu trữ của mình, điều này được thực hiện đơn giản bằng cách mở rộng QueryDslPredicateExecutor giao diện :

public interface UserRepository extends 
  MongoRepository<User, String>, QuerydslPredicateExecutor<User>

5.4. Phương trình

Khi hỗ trợ được bật, bây giờ hãy triển khai các truy vấn tương tự như những cái chúng tôi đã minh họa trước đây.

Chúng ta sẽ bắt đầu với sự bình đẳng đơn giản:

QUser qUser = new QUser("user");
Predicate predicate = qUser.name.eq("Eric");
List<User> users = (List<User>) userRepository.findAll(predicate);

5.5. Bắt đầu với EndingWith

Tương tự, hãy triển khai các truy vấn trước đó và tìm người dùng có tên bắt đầu bằng A :

QUser qUser = new QUser("user");
Predicate predicate = qUser.name.startsWith("A");
List<User> users = (List<User>) userRepository.findAll(predicate);

Cũng như kết thúc bằng c :

QUser qUser = new QUser("user");
Predicate predicate = qUser.name.endsWith("c");
List<User> users = (List<User>) userRepository.findAll(predicate);

Kết quả tương tự như trong phần 2.2, 3.2 và 4.2.

5.6. Giữa

Truy vấn tiếp theo sẽ trả về những người dùng có độ tuổi từ 20 đến 50, tương tự như các phần trước:

QUser qUser = new QUser("user");
Predicate predicate = qUser.age.between(20, 50);
List<User> users = (List<User>) userRepository.findAll(predicate);

  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Tạo Bộ sưu tập trong MongoDB

  2. Cách hợp nhất tài liệu khi nhập tệp vào MongoDB

  3. lưu địa chỉ IP trong mongoDB

  4. Làm thế nào để so sánh dữ liệu Morphia, Mongo4j và Spring cho MongoDB?

  5. Tôi có thể thực hiện truy vấn văn bản với trình điều khiển mongodb c # không