/spring-boot-starter-data-search

Spring-Data search API augmented with Natural Language support.

Primary LanguageJavaApache License 2.0Apache-2.0

build Security Rating Maintainability Rating Reliability Rating Coverage Bugs Quality Gate Status

spring-boot-starter-data-search

Spring Data Search API augmented with Natural Language support.

Already supported:

Data Search is compatible with Spring Native (see the list of supported drivers and limitations)

Coming soon:

Demo:
spring-boot-starter-data-search-mongodb-demo
spring-boot-starter-data-search-jpa-demo

Table of Contents

Data Search

Data Search provides an enterprise & production ready API, prowered by Spring Boot and Antlr, to query your data, and perform advanced search with Natural Language.

Search example: users born after 1988-01-01, with an gmail or protonmail email address, having completed the email verification, and having an address in one of the following countries: France, Switzerland or China

birthDate >: '1988-01-01' and (emailAddress : *gmail.com or emailAddress: *protonmail.com) and emailAddressVerified: true and addresses.countryCode: 'FR,CH,CN'

Features

  • Logical operators (or/ and)
  • Parenthesis/ criteria prioritization
  • Mongodb and all JPA compatible db engines
  • Fields mapping/ DTO to Entities
  • Filter by subentity fields/ deep search
  • Advanced RegEx for Mongodb and like operator for JPA
  • All comparison operators

Comparison operators

Equal :

emailAddressVerified : true

Not equal !:

emailAddressVerified !: true

In :

countryCode : 'FR,CH,CN'

Not in :

countryCode !: 'FR,CH,CN'

Starts with :

firstName: S*

Ends with :

firstName: *S

Contains :

firstName: *S*

Less than <

birthDate < '1988-01-01'

Less than or equal <:

birthDate <: '1988-01-01'

Greater than >

birthDate > '1988-01-01'

Greater than or equal >:

birthDate >: '1988-01-01'

Exists (is not null)

birthDate

Doesn't exist (is null) !

!birthDate

Supported values

String

firstName : Stan

Enum

title : MR

Boolean

emailAddressVerified : true

Number (Integer, Double, Long, BigDecimal)

ref >: 100 or coins > 6.76453

LocalTime

time >: '18:58:24' and time <: '18:58:24.999'

OffsetTime

time >: '18:58:24Z' and time <: '20:58:24.999+02:00'

LocalDate

birthDate >: '1988-01-01'

LocalDateTime

createdDate >: '2021-08-23T18:58:24' and createdDate <: '2021-10-12T18:58:24.000'

OffsetDateTime

createdDate >: "2021-08-23T18:58:24Z" and createdDate <: '2021-10-12T18:58:24.000+02:00'

Array

countryCode : 'FR,CH,CN'

RegEx

emailAddress : '/.*gmail.com/' Regular expression, supported only for mongodb (see documentation) |

Detailed use case

See detailed search use case here

Getting Started

Requirements

Java version 11 or higher (If java 8 support is needed, please vote for this issue)

SpringBoot version 2.1.0 or higher

Demo

Mongodb demo

https://github.com/commerce-io/spring-boot-starter-data-search-mongodb-demo

JPA demo

https://github.com/commerce-io/spring-boot-starter-data-search-jpa-demo

Installation

➡️ Get the latest releases here ⬅️

Data Search Mongodb starter

Maven

<dependency>
    <groupId>app.commerce-io</groupId>
    <artifactId>spring-boot-starter-data-search-mongodb</artifactId>
    <version>1.3.0</version>
</dependency>

Gradle implementation 'app.commerce-io:spring-boot-starter-data-search-mongodb:1.3.0'

Data Search JPA Starter

Maven

<dependency>
    <groupId>app.commerce-io</groupId>
    <artifactId>spring-boot-starter-data-search-jpa</artifactId>
    <version>1.3.0</version>
</dependency>

Gradle implementation 'app.commerce-io:spring-boot-starter-data-search-jpa:1.3.0'

Configuration

Data Search provides a custom repository. In order to use the provided repository, add the following annotation to the main class or any other configuration class.

Mongodb Repository

@Configuration
@EnableMongoRepositories(repositoryBaseClass = SearchRepositoryImpl.class)
public class DemoConfiguration {
}

JPA Repository

@Configuration
@EnableJpaRepositories(repositoryBaseClass = SearchRepositoryImpl.class)
public class DemoConfiguration {
}

Usage

Make your repositories extend SearchRepository

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

And use in a controller or from anywhere else

@RestController
@RequiredArgsConstructor
public class DemoController {

    private final CustomerRepository customerRepository;

    @Transactional(readOnly = true)
    @RequestMapping(
            method = RequestMethod.GET,
            value = "/customers",
            produces = {"application/json"}
    )
    public ResponseEntity<Page<Customer>> searchCustomers(
            @RequestParam(value = "search", required = false) String search,
            Pageable pageable) {

        Page<Customer> customerPage = customerRepository.findAll(
                search,
                pageable);

        return ok(customerPage);
    }
}

Field Mapping

Users will tend to filter by the search result fields, and sometimes, your DTO structure differs from your entity/ collection. Data search provides a mapper, to define your custom mappings rules in two different ways:

Flat Mapper

The flat mapper is a basic String to String mapping, which could be useful for simple use cases.

String search = "addressName: test";
Mapper addressMapper = Mapper.flatMapper()
            .mapping("addressName", "address.firstName")
            .build();

Page<CustomerEntity> page = customerRepository.findAll(search, pageable, addressMapper);

Advanced Mapper

The advanced mapper is used for complex structure mapping, and enable the reuse of mappers. Advanced mappers can be combined with flat mappers.

String search = "name: test OR address.addressName: test";
Mapper addressMapper = Mapper.flatMapper()
            .mapping("addressName", "firstName")
            .build();

Mapper mapper = Mapper.mapper()
                .mapping("name", "firstName")
                .mapping("address", "addressEntity", addressMapper)
                .build();

Page<CustomerEntity> page = customerRepository.findAll(search, pageable, mapper);

Value Mapping

In addition to the fields mapping, some values could be converted before returning the search result. Data Search supports values mapping:

public class LowerCaseValueMapping implements ValueMapping {

  @Override
  public String map(String from) {
    return from == null ? null : from.toLowerCase();
  }
}
String search = "addressName: TeSt";
Mapper addressMapper = Mapper.flatMapper()
        .mapping("addressName", "address.firstName", new LowerCaseValueMapping())
        .build();

Page<CustomerEntity> page = customerRepository.findAll(search, pageable, addressMapper);

Contributors

All Contributors

Thanks to these wonderful people (emoji key):


@adlmez

💻 🤔 👀 💡 ⚠️

Dependabot

🚇

All Contributors

🚇

This project follows the all-contributors specification. Contributions of any kind welcome!

License

license

This software is released under the Apache license. See LICENSE for more information.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!