使用限制并跳过MongorePository< customer,string>

发布于 2025-01-21 14:17:02 字数 388 浏览 0 评论 0 原文

我们正在从事一个项目,以从MongoDB获取数据。我们已经创建了存储库类,如下所示,

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String>{
     List<Customer> customers = findByCustomerId(final String customerId);
}

我们希望添加Skip/Offset,并限制参数以作为FindbyCustomerId方法的一部分。使用限制来定义返回的记录数量并跳过/偏移定义我们需要获取记录的记录数。

请帮助我们如何使用Mongorepository以最佳方式实现此目标。

We are working on a project to get data from mongoDB. We have created repository class as below

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String>{
     List<Customer> customers = findByCustomerId(final String customerId);
}

We are looking to add skip/offset and limit parameters to be used as part of findByCustomerId method. where limit is used to define number of records returned and skip/offset defines the number of records after which we need to get the records.

Please help how we can get this implemented in best way using MongoRepository.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

三寸金莲 2025-01-28 14:17:02

有两种方法可以做到这一点。

  1. 使用 @Aggregation 注释,如本答案中所述。
    https://stackoverflow.com/a/71292598/84700555

例如:例如

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String>{

  @Aggregation(pipeline = {
    "{ '$match': { 'customerId' : ?0 } }", 
    "{ '$sort' : { 'customerId' : 1 } }", 
    "{ '$skip' : ?1 }", 
    "{ '$limit' : ?2 }"
  })
  List<Customer> findByCustomerId(final String customerId, int skip, int limit);

  @Aggregation(pipeline = {
    "{ '$match': { 'customerId' : ?0 } }", 
    "{ '$sort' : { 'customerId' : 1 } }", 
    "{ '$skip' : ?1 }"
  })
  Page<Customer> findCustomers(final String customerId, int skip, Pageable pageable);

}

:操作员的查询可能需要修改,以便更好地反映匹配文档需要满足的条件。

  1. 在查询方法中使用 Pagable 参数,并从调用存储库方法的图层中提供 pagerequest ,如本答案所示。
    https://stackoverflow.com/a/100777534/84700555

对于这个问题,对于这个问题而言,对于代码smine而言。

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String> {

  Page<Customer> findByCustomerId(final String customerId, Pageable pageable);

}

// -------------------------------------------------------
// Call the repository method from a service
@Service
public class CustomerService {

  private final CustomerRepository customerRepository;

  public CustomerService(CustomerRepository customerRepository) {
    this.customerRepository = customerRepository;
  }

  public List<Customer> getCustomers(String customerId, int skip, int limit) {
    // application-specific handling of skip and limit arguments
    int page = 1; // calculated based on skip and limit values
    int size = 5; // calculated based on skip and limit values
    Page<Customer> page = customerRepository.findByCustomerId(customerId, 
                 PageRequest.of(page, size, Sort.Direction.ASC, "customerId"));
    List<Customer> customers = page.getContent();

    /*
    Here, the query method will retrieve 5 documents from the second 
    page.
    It skips the first 5 documents in the first page with page index 0. 
    This approach requires calculating the page to retrieve based on 
    the application's definition of limit/skip.
    */
    return Collections.unmodifiableList(customers);
  }
}

聚合方法更有用。
如果结果仅限于几个文档,则查询方法可以返回 list&lt; customer&gt;
如果有很多文档,则可以修改查询方法以使用 Pagable 参数,该参数返回 page&lt; customer&gt; 通过文档上的页面。

请参阅Spring Data和MongoDB文档。

https://docs.spring。 io/spring-data/mongodb/docs/3.2.10/reference/html/#mongo.repositories

https://docs.spring.io/spring.io/spring-data/mongodb/docb/docs/3.2.2.10/reference/reference/reference/reference/html/#mongongodb .repositories.queries.aggregation

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/api/org/springframework/data/mongodb/repository/Aggregation.html

mongodb聚合 - https://www.mongodb.com/docs/manual/meta/meta/aggregation-quick-reference/

动态查询

自定义弹簧数据存储库以及使用 mongotemplate 应有助于实现实施动态查询。

自定义存储库 -

mongotemplate -

There are two ways to do this.

  1. Use of @Aggregation annotation as mentioned in this answer.
    https://stackoverflow.com/a/71292598/8470055

For example:

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String>{

  @Aggregation(pipeline = {
    "{ '$match': { 'customerId' : ?0 } }", 
    "{ '$sort' : { 'customerId' : 1 } }", 
    "{ '$skip' : ?1 }", 
    "{ '$limit' : ?2 }"
  })
  List<Customer> findByCustomerId(final String customerId, int skip, int limit);

  @Aggregation(pipeline = {
    "{ '$match': { 'customerId' : ?0 } }", 
    "{ '$sort' : { 'customerId' : 1 } }", 
    "{ '$skip' : ?1 }"
  })
  Page<Customer> findCustomers(final String customerId, int skip, Pageable pageable);

}

The $match operator's query might need to be modified so that it better reflects the condition that needs to be satisfied by the matching documents.

  1. Use Pageable argument in the query method and supply the PageRequest from the layer that calls the Repository method as shown in this answer.
    https://stackoverflow.com/a/10077534/8470055

For the code snippet in the question this then becomes.

@Repository
public interface CustomerRepository extends MongoRepository<Customer,String> {

  Page<Customer> findByCustomerId(final String customerId, Pageable pageable);

}

// -------------------------------------------------------
// Call the repository method from a service
@Service
public class CustomerService {

  private final CustomerRepository customerRepository;

  public CustomerService(CustomerRepository customerRepository) {
    this.customerRepository = customerRepository;
  }

  public List<Customer> getCustomers(String customerId, int skip, int limit) {
    // application-specific handling of skip and limit arguments
    int page = 1; // calculated based on skip and limit values
    int size = 5; // calculated based on skip and limit values
    Page<Customer> page = customerRepository.findByCustomerId(customerId, 
                 PageRequest.of(page, size, Sort.Direction.ASC, "customerId"));
    List<Customer> customers = page.getContent();

    /*
    Here, the query method will retrieve 5 documents from the second 
    page.
    It skips the first 5 documents in the first page with page index 0. 
    This approach requires calculating the page to retrieve based on 
    the application's definition of limit/skip.
    */
    return Collections.unmodifiableList(customers);
  }
}

The aggregation approach is more useful.
If the result is limited to a few documents then the query method can return List<Customer>.
If there a lot of documents then the query method can be modified to use Pageable argument that returns Page<Customer> to page over the documents.

Refer to both Spring Data and MongoDB documentation.

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/reference/html/#mongo.repositories

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/reference/html/#mongodb.repositories.queries.aggregation

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/api/org/springframework/data/mongodb/repository/Aggregation.html

https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Pageable.html

https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html

MongoDB Aggregation - https://www.mongodb.com/docs/manual/meta/aggregation-quick-reference/

Dynamic Queries

Custom Spring Data repository implementation along with use of MongoTemplate should help in implementing dynamic queries.

Custom Repositories - https://docs.spring.io/spring-data/mongodb/docs/3.2.10/reference/html/#repositories.custom-implementations

MongoTemplate - https://docs.spring.io/spring-data/mongodb/docs/3.2.10/api/org/springframework/data/mongodb/core/MongoTemplate.html

好听的两个字的网名 2025-01-28 14:17:02

一个简单的用例是将自定义存储库与查询和SimpleMongorePosority类一起使用。

customerrepository.java

@Repository
public interface CustomerRepository extends ResourceRepository<Customer, String> {
}

resourceRepository.java

@NoRepositoryBean
public interface ResourceRepository<T, I> extends MongoRepository<T, I> {

    Page<T> findAll(Query query, Pageable pageable);
}

resourcercerepositoryimpl.java

@SuppressWarnings("rawtypes")
public class ResourceRepositoryImpl<T, I> extends SimpleMongoRepository<T, I> implements ResourceRepository<T, I> {

    private MongoOperations mongoOperations;

    private MongoEntityInformation entityInformation;

    public ResourceRepositoryImpl(final MongoEntityInformation entityInformation, final MongoOperations mongoOperations) {
        super(entityInformation, mongoOperations);

        this.entityInformation = entityInformation;
        this.mongoOperations = mongoOperations;
    }

    @Override
    public Page<T> findAll(final Query query, final Pageable pageable) {
        Assert.notNull(query, "Query must not be null!");

        long total = mongoOperations.count(query, entityInformation.getJavaType(), entityInformation.getCollectionName());
        List<T> content = mongoOperations.find(query.with(pageable), entityInformation.getJavaType(), entityInformation.getCollectionName());

        return new PageImpl<T>(content,pageable,total);
    }
}

customerservice.java

@RequiredArgsConstructor
@Service
public class CustomerService {

   private final CustomerRepository repository;

    /**
     * @param customerId
     * @param limit the size of the page to be returned, must be greater than 0.
     * @param page zero-based page index, must not be negative.
     * @return Page of {@link Customer}
     */
    public Page<Customer> getCustomers(String customerId, int limit, int page) {
        Query query = new Query();
        query.addCriteria(Criteria.where("customerId").is(customerId));
        return repository.findAll(query, PageRequest.of(page, limit, Sort.by(Sort.Direction.ASC, "customerId")));
    }

    public List<Customer> getCustomersList(String customerId, int limit, int page) {
        Page<Customer> customerPage = getCustomers(customerId, limit, page);
        return customerPage.getContent();
    }
}

带有特定标准的参考:
https://dzone.com/articles/articles/advanced-搜索 - 滤波器滤清器 - us-spring-dat

A simple use case is to use a custom repository with the Query and SimpleMongoRepository classes.

CustomerRepository.java

@Repository
public interface CustomerRepository extends ResourceRepository<Customer, String> {
}

ResourceRepository.java

@NoRepositoryBean
public interface ResourceRepository<T, I> extends MongoRepository<T, I> {

    Page<T> findAll(Query query, Pageable pageable);
}

ResourceRepositoryImpl.java

@SuppressWarnings("rawtypes")
public class ResourceRepositoryImpl<T, I> extends SimpleMongoRepository<T, I> implements ResourceRepository<T, I> {

    private MongoOperations mongoOperations;

    private MongoEntityInformation entityInformation;

    public ResourceRepositoryImpl(final MongoEntityInformation entityInformation, final MongoOperations mongoOperations) {
        super(entityInformation, mongoOperations);

        this.entityInformation = entityInformation;
        this.mongoOperations = mongoOperations;
    }

    @Override
    public Page<T> findAll(final Query query, final Pageable pageable) {
        Assert.notNull(query, "Query must not be null!");

        long total = mongoOperations.count(query, entityInformation.getJavaType(), entityInformation.getCollectionName());
        List<T> content = mongoOperations.find(query.with(pageable), entityInformation.getJavaType(), entityInformation.getCollectionName());

        return new PageImpl<T>(content,pageable,total);
    }
}

CustomerService.java

@RequiredArgsConstructor
@Service
public class CustomerService {

   private final CustomerRepository repository;

    /**
     * @param customerId
     * @param limit the size of the page to be returned, must be greater than 0.
     * @param page zero-based page index, must not be negative.
     * @return Page of {@link Customer}
     */
    public Page<Customer> getCustomers(String customerId, int limit, int page) {
        Query query = new Query();
        query.addCriteria(Criteria.where("customerId").is(customerId));
        return repository.findAll(query, PageRequest.of(page, limit, Sort.by(Sort.Direction.ASC, "customerId")));
    }

    public List<Customer> getCustomersList(String customerId, int limit, int page) {
        Page<Customer> customerPage = getCustomers(customerId, limit, page);
        return customerPage.getContent();
    }
}

A reference with specific criteria:
https://dzone.com/articles/advanced-search-amp-filtering-api-using-spring-dat

你是年少的欢喜 2025-01-28 14:17:02

我已经使用了$ skip和$ limit的聚合查询,它可以正常工作,并且当您需要分页一个复杂的查询结果时非常有用。对于更简单的查询,我使用了采用查询对象的Spring Mongo模板。查询对象采用一个可打印的对象,其中您使用排序选项定义页码和页面大小。

Criteria criterion = Criteria.where("field").is("value");//build your criteria here.
Query query = new Query(criterion);

Sort fieldSorting = Sort.by(Sort.Direction.DESC, "sortField"); // sort field 
        
int pageNo = 1; //which page you want to fetch. NoOfPages = TotalRecords/PageZie 
int pagesize = 10; // no of records per page
Pageable pageable = PageRequest.of(pageNo, pagesize, fieldSorting); // define your page

mongoTemplate.find(query.with(pageable), Object.class); // provide appropriate DTO class to map.

对于mongo db聚合选项 -

I have used the Aggregation query with $skip and $limit, it works fine and is quite useful when you need to Paginate a complex piece of a query result. For simpler queries, I use the spring mongo template which takes a Query object. The query object takes a Pageable object where you define a page number and page size with a sorting option.

Criteria criterion = Criteria.where("field").is("value");//build your criteria here.
Query query = new Query(criterion);

Sort fieldSorting = Sort.by(Sort.Direction.DESC, "sortField"); // sort field 
        
int pageNo = 1; //which page you want to fetch. NoOfPages = TotalRecords/PageZie 
int pagesize = 10; // no of records per page
Pageable pageable = PageRequest.of(pageNo, pagesize, fieldSorting); // define your page

mongoTemplate.find(query.with(pageable), Object.class); // provide appropriate DTO class to map.

For mongo DB aggregation options - https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit/
https://www.mongodb.com/docs/manual/reference/operator/aggregation/skip/

今天小雨转甜 2025-01-28 14:17:02

限制查询结果的另一种(也许更简单的)方法是在使用 mongorePository 时在方法声明中添加过滤器。两个关键字 top first 均可用于达到此目标,还指定了所需的结果量(或通过省略,仅获得一个结果)。

下面的代码是一个示例,在 docs.spring.io 文档中可用, mongorePosories (下面的链接)。

User findFirstByOrderByLastnameAsc();

User findTopByOrderByAgeDesc();

Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);

Slice<User> findTop3ByLastname(String lastname, Pageable pageable);

List<User> findFirst10ByLastname(String lastname, Sort sort);

List<User> findTop10ByLastname(String lastname, Pageable pageable);

您也可以将分页应用于查询(更多详细信息
文档)。

有关排序的一些额外信息:

,其他答案也给了一些有关分类的见解,我想在这方面带来其他选择。

如果您的方法始终以相同的方式对结果进行排序,则可以在方法声明中使用 orderby 关键字进行排序,然后使用 asc desc 取决于您的用例。

List<User> findFirst10ByLastnameOrderByAgeAsc(String lastname);

List<User> findFirst10ByLastnameOrderByAgeDesc(String lastname);

如果您想动态地对结果进行分类,则可以在方法上使用 sort 参数并提供。

List<User> findFirst10ByLastname(String lastname, Sort sort);

例如,在方法调用中提供 sort.by(desc,“ age”)将定义 {age:-1} 作为查询的排序。

参考

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/reference/html/#repositories.query-methods

Another (maybe simpler) approach for limiting the results of the query is adding the filters in the method declaration when using MongoRepository. Both the keywords top and first can be used to reach this goal, specifying also the amount of results desired (or by omitting it, obtaining thus just one result).

The code below is an example, available in the docs.spring.io documentation for MongoRepositories (link below).

User findFirstByOrderByLastnameAsc();

User findTopByOrderByAgeDesc();

Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);

Slice<User> findTop3ByLastname(String lastname, Pageable pageable);

List<User> findFirst10ByLastname(String lastname, Sort sort);

List<User> findTop10ByLastname(String lastname, Pageable pageable);

You can also apply pagination to your query (more details in the
documentation).

SOME EXTRA INFORMATION ABOUT SORTING:

As the other answers also gave some insight about the sorting, I would like to bring other options in this regard.

If your method will always sort the results in the same way, the sorting can be made by using the OrderBy keyword in your method declaration, followed by Asc or Desc depending on your use-case.

List<User> findFirst10ByLastnameOrderByAgeAsc(String lastname);

List<User> findFirst10ByLastnameOrderByAgeDesc(String lastname);

If you would like to sort your results dynamically, you can use the Sort argument on your method and provide.

List<User> findFirst10ByLastname(String lastname, Sort sort);

As an example, providing Sort.by(DESC, "age") in the method call will define { age : -1 } as the sort for the query.

References:

https://docs.spring.io/spring-data/mongodb/docs/3.2.10/reference/html/#repositories.query-methods

深陷 2025-01-28 14:17:02

我没有返回列表,而是尝试了可选的,并且可以使用。
在此示例中,如果存在,它将返回最新记录:

@Repository
public interface IoTTriggerDao extends MongoRepository<IotDECTrigger, String> {

@Query(value = """
    {
       "$and":
       [
          { 'dec._id' : ?0, 'active': false, 'runSingleTime': true },
          { 'processing' : false, 'ended': true}
       ]
    }
    """, sort = "{ 'activeFromDateEpoch' : -1 }")
Optional<IotDECTrigger> getDECSingleTimeFinishedTrigger(String decId);

}

Instead of returning List, I've tried with Optional, and it works.
In this example, it returns newest record if it exists :

@Repository
public interface IoTTriggerDao extends MongoRepository<IotDECTrigger, String> {

@Query(value = """
    {
       "$and":
       [
          { 'dec._id' : ?0, 'active': false, 'runSingleTime': true },
          { 'processing' : false, 'ended': true}
       ]
    }
    """, sort = "{ 'activeFromDateEpoch' : -1 }")
Optional<IotDECTrigger> getDECSingleTimeFinishedTrigger(String decId);

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文