Getting started

Only a few steps are necessary to get started with a standard configuration. Several code examples can be found here.

Start Elasticsearch

picturesafe-search requires a running Elasticsearch server from version 7.x.

Local installation of Elasticsearch

For a new application an Elasticsearch server must be installed first:

  • Download and unpack the Elasticsearch official distribution.
  • Run bin/elasticsearch on Linux or macOS. Run bin\elasticsearch.bat on Windows.

Some features of picturesafe-search (for example sorting documents in a language-specific word order) require the ICU Analysis Plugin for Elasticsearch:

  • Run bin/elasticsearch-plugin install analysis-icu on Linux or macOS. Run bin\elasticsearch-plugin install analysis-icu on Windows.

Run Elasticsearch in a Docker container

As an alternative to installing Elasticsearch you can run it in a Docker container. To do this you can use the provided Docker Compose file.

  • Install Docker and Docker Compose.
  • Clone the picturesafe-search GitHub repository.
  • Run docker-compose -f src/test/docker/docker-compose.yml up -d from the project directory to start Elasticsearch.
  • To stop Elasticsearch run docker-compose -f src/test/docker/docker-compose.yml stop from the project directory.

Include java library

Add the current version of the picturesafe-search library to your project.

Maven dependency

<dependency>
    <groupId>de.picturesafe.search</groupId>
    <artifactId>picturesafe-search</artifactId>
    <version>3.5.0</version>
</dependency>

Configuration

Configuration bean

Implement a configuration class that imports the DefaultElasticConfiguration.class. This configuration can be extended later.

The following example defines three fields for the Elasticsearch index:

  • Field ‘id’ (Elasticsearch type text, sortable)
  • Field ‘fulltext’ (Elasticsearch type text)
  • Field ‘title’ (Elasticsearch type text, within fulltext, aggregatable, sortable)
  • Field ‘count’ (Elasticsearch type integer, sortable)

Spring configuration

@Configuration
@ComponentScan(basePackages = {"de.picturesafe.search.elasticsearch"})
@Import({DefaultElasticConfiguration.class})
public class Config {

    @Bean
    List<FieldConfiguration> fieldConfigurations() {
        return Arrays.asList(
            FieldConfiguration.ID_FIELD,
            FieldConfiguration.FULLTEXT_FIELD,
            StandardFieldConfiguration.builder(
                    "title", ElasticsearchType.TEXT).copyToFulltext(true).sortable(true).build(),
            StandardFieldConfiguration.builder(
                    "count", ElasticsearchType.INTEGER).sortable(true).build()
        );
    }
}

Configuration properties

Add a file elasticsearch.properties to the classpath of your application and define the following key (this configuration can be extended later):

Property file

elasticsearch.index.alias_name=picturesafe-search-sample

Service implementation

Inject the SingleIndexElasticsearchService and implement an expression-based search:

  • Create an Elasticsearch index with alias
  • Add some documents to the index
  • Create an OperationExpression with two terms
  • Run the search query
  • Delete the Elasticsearch index

If you want to implement searches for more than one index, please use ElasticsearchService instead of SingleIndexElasticsearchService.

Spring service implementation

@Component
@ComponentScan
public class GettingStarted {

    private static final Logger LOGGER = LoggerFactory.getLogger(GettingStarted.class);

    @Autowired
    private SingleIndexElasticsearchService singleIndexElasticsearchService;

    public static void main(String[] args) {
        final AnnotationConfigApplicationContext ctx
            = new AnnotationConfigApplicationContext(GettingStarted.class);
        final GettingStarted gettingStarted = ctx.getBean(GettingStarted.class);
        gettingStarted.run();
        ctx.close();
    }

    private void run() {
        singleIndexElasticsearchService.createIndexWithAlias();

        singleIndexElasticsearchService.addToIndex(DataChangeProcessingMode.BLOCKING, Arrays.asList(
                DocumentBuilder.id(1).put("title", "This is a test title").put("count", 101).build(),
                DocumentBuilder.id(2).put("title", "This is another test title").put("count", 102).build(),
                DocumentBuilder.id(3).put("title", "This is one more test title").put("count", 103).build()
        ));

        final Expression expression = OperationExpression.and(
                new FulltextExpression("test title"),
                new ValueExpression("count", ValueExpression.Comparison.GE, 102));

        final SearchResult searchResult = singleIndexElasticsearchService
            .search(expression, SearchParameter.DEFAULT);

        LOGGER.info(searchResult.toString());

        singleIndexElasticsearchService.deleteIndexWithAlias();
    }
}

With implementations of the picturesafe-search Expression-Interface complex terms of different search conditions can be easily defined.

Here are some examples:

Simple fulltext search

Expression expression = new FulltextExpression("test title");

Simple field search

Expression expression = new ValueExpression("title", "test");

Simple field search with comparison operator

Expression expression = new ValueExpression("count", ValueExpression.Comparison.GE, 102);

Search with two terms

Expression expression = OperationExpression.and(
    new FulltextExpression("test title"),
    new ValueExpression("count", ValueExpression.Comparison.GE, 102));

In addition there are further Expressions like InExpression, MustNotExpression, RangeValueExpression, DayExpression, …