简体   繁体   中英

How can I reduce the Complexity of this code?

I'm trying to create a search method by DTO. I mean users can search products by one more field. Can you suggest any better way for that or help to reduce the complexity of this one?

public List<ProductDTO> search(SearchProductDTO productDTO) {
    Criteria criteria = null;
    String insensitive = "i";
    if (StringUtils.isNotBlank(productDTO.getName()))
        criteria = Criteria.where(NAME.getLabel()).regex(productDTO.getName(), insensitive);
    if (StringUtils.isNotBlank(productDTO.getDescription()))
        criteria = criteria != null ? criteria.and(DESCRIPTION.getLabel()).regex(productDTO.getDescription(), insensitive) : Criteria.where(DESCRIPTION.getLabel()).regex(productDTO.getDescription(), insensitive);
    if (productDTO.getPrice() != 0)
        criteria = criteria != null ? criteria.and(PRICE.getLabel()).is(productDTO.getPrice()) : Criteria.where(PRICE.getLabel()).is(productDTO.getPrice());
    if (StringUtils.isNotBlank(productDTO.getBrand()))
        criteria = criteria != null ? criteria.and(BRAND.getLabel()).regex(productDTO.getBrand(), insensitive) : Criteria.where(BRAND.getLabel()).regex(productDTO.getBrand(), insensitive);
    if (productDTO.getProductSize() != null)
        criteria = criteria != null ? criteria.and(SIZE.getLabel()).is(productDTO.getProductSize()) : Criteria.where(SIZE.getLabel()).is(productDTO.getProductSize());
    if (productDTO.getStockCount() != 0)
        criteria = criteria != null ? criteria.and(STOCK_COUNT.getLabel()).is(productDTO.getStockCount()) : Criteria.where(STOCK_COUNT.getLabel()).is(productDTO.getStockCount());
    if (StringUtils.isNotBlank(productDTO.getType()))
        criteria = criteria != null ? criteria.and(TYPE.getLabel()).regex(productDTO.getType(), insensitive) : Criteria.where(TYPE.getLabel()).regex(productDTO.getType(), insensitive);
    if (StringUtils.isNotBlank(productDTO.getColor()))
        criteria = criteria != null ? criteria.and(COLOR.getLabel()).regex(productDTO.getColor(), insensitive) : Criteria.where(COLOR.getLabel()).regex(productDTO.getColor(), insensitive);
    if (productDTO.getGender() != null)
        criteria = criteria != null ? criteria.and(GENDER.getLabel()).is(productDTO.getGender()) : Criteria.where(GENDER.getLabel()).is(productDTO.getGender());
    Pageable pageable = PageRequest.of(productDTO.getPage(), productDTO.getSize());
    Query query = new Query().with(pageable);
    query = criteria != null ? query.addCriteria(criteria).with(pageable) : query;
    List<Product> products = mongoTemplate.find(query, Product.class);
    return products.stream().map(productMapper::modelToDto).collect(Collectors.toList());
}

One nicer thing to do would be to externalize the null check + appending of where clause + assignment of parameters into it's own method. This way your code will be more understandable.

You could also wrap the Criteria class and add for example „optionalWhere()“ which does the null check and appends the where clause only if the parameter has a value.

...Unfortunately I don't know why the problem of dynamic queries, as for searches from a GUI, are not addressed in the APi itself...

You can get rid of null-checks by dynamically collecting criterias into list and combining this list into single "multi"-criteria

List<Criteria> criterias = new ArrayList<>();

// collect
if (StringUtils.isNotBlank(productDTO.getName()))
    criterias.add(Criteria.where(NAME.getLabel()).regex(productDTO.getName(), insensitive));
if (StringUtils.isNotBlank(productDTO.getDescription()))
    criterias.add(Criteria.where(DESCRIPTION.getLabel()).regex(productDTO.getDescription(), insensitive));
if (productDTO.getPrice() != 0)
    criterias.add(Criteria.where(PRICE.getLabel()).is(productDTO.getPrice()));
// and so on ...

// combine
Criteria multiCriteria = new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()]));

// use
Pageable pageable = PageRequest.of(productDTO.getPage(), productDTO.getSize());
Query query = new Query().with(pageable);
query.addCriteria(multiCriteria);

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