简体   繁体   中英

I want to filter a list of object in groovy

This is my groovy class

Asset {
    ObjectState objectState = ObjectState.CURRENT
    String description
    @NotEmpty(message = "*Please provide a asset name")
    @Length(min = 2, max = 50, message = "*Asset name must have characters between 2 and 50")
    String assetName
    @DBRef
    Company company
}

I want to find those assets of a particular company which contains "test" in assetName and description

Now i implemented the business logic like this

@Override
    Page<Asset> fetchAssetsBySearchStringAndObjectStateAndCompany(Company company, Pageable pageable, String searchQuery) {
        ObjectState objectState = ObjectState.CURRENT
        if (!pageable) {
            pageable = PageRequest.of(0, 10, Sort.Direction.DESC, "lastUpdated")
        }
        if (searchQuery) {
            Page<Asset> assets = assetRepository.findAllByCompanyAndObjectState(company, pageable, objectState)
            List<Asset> filteredAssets = []
            assets.each {
                if (it.assetName.contains(searchQuery) || it.description.contains(searchQuery)) {
                    filteredAssets.add(it)
                }
            }
           return filteredAssets // i want this list in pagination object
        } else {
            return assetRepository.findAllByCompanyAndObjectState(company, pageable, objectState)
        }
    }
  1. I find all the assets of a company -

  2. Filter out the "test" string using groovy closure - assets.each { }

  3. Now my filteredAssets contains required result but i want this in pagination object

Now my question is

1- Is this approach is efficient

2- How to convert filteredAssets in Page

I also tried to use mongo native query but i am unable to convert it to spring boot

@Query('''{ 
               'company': ?0,
               $or :
                    [
                        {'assetName' : { $regex: ?1, $options:'i' }},
                        {'description' : { $regex: ?1, $options:'i' }},
                    ]
            }
           ''')
Page<Asset> findAllByCompanyAndAssetNameOrDescription(Company company, String assetName, Pageable pageable)

I don't have a specific answer but my suggestion is that your first approach is not going to work at a higher level because you are filtering the results after the pagination has been performed by the initial query. So you will potentially end up with less than the desired page size (or even an empty result) even though there are valid results that could have been returned by the query.

In other words, to achieve this you really do need to use the second approach of constructing a native query that incorporates the filtering. To resolve why that is not working, you would need to post more information about the kind of errors you are seeing (or possibly put it as a separate question and close this one out).

EDIT : to answer the question more specifically - if you choose to persist with the approach, it looks to me like you can construct your own Page object by harnessing the Spring data PageImpl object which has a usable constructor from a list of elements. You can simply construct this object from your filtered list of elements - ie: instead of this:

    ...
    return filteredAssets

Do this:

   return new PageImpl(filteredAssets)

If you want to be more idiomatic with your groovy code I would also suggest to change the filtering operation to use findAll . In that case the code gets more compact:

    return new PageImpl(assets.findAll { it.assetName.contains(searchQuery) })

Once again though I would caution that from looking at your problem I don't think it's going to have the result you actually want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM