|
This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Data Meilisearch 0.8.1! |
Meilisearch Operations
Spring Data Meilisearch uses several interfaces to define the operations that can be called against a Meilisearch index.
-
DocumentOperationsdefines actions to store, update and retrieve entities based on their id. -
SearchOperationsdefines the actions to search for multiple entities using queries. -
MeilisearchOperationscombines theDocumentOperationsandSearchOperationsinterfaces.
These interfaces correspond to the structuring of the Meilisearch API.
The default implementations of the interfaces offer:
-
Read/Write mapping support for domain types
-
A rich query API
-
Resource management and exception translation
Usage examples
The example shows how to use an injected MeilisearchOperations instance in a Spring REST controller.
The example assumes that Movie is a class that is annotated with @Document, @Id etc.
@RestController
@RequestMapping("/")
public class MovieController {
private MeilisearchOperations meilisearchOperations;
public MovieController(MeilisearchOperations meilisearchOperations) { (1)
this.meilisearchOperations = meilisearchOperations;
}
@PostMapping("/movie")
public String save(@RequestBody Movie movie) { (2)
Movie savedEntity = meilisearchOperations.save(movie);
return savedEntity.getId();
}
@GetMapping("/movie/{id}")
public Movie findById(@PathVariable("id") String id) { (3)
return meilisearchOperations.get(id, Movie.class);
}
}
| 1 | Let Spring inject the provided MeilisearchOperations bean in the constructor. |
| 2 | Store a movie in the Meilisearch instance. |
| 3 | Retrieve the movie by id. |
Search Result Types
When searching with the methods of the SearchOperations interface, additional information is available for each entity.
The following classes and interfaces are available:
Contains the following information:
-
The retrieved entity of type <T> (content)
-
Processing time in milliseconds (processingTimeMs)
-
The search query string (query)
-
Facet statistics if available (facetStats)
-
Facet distribution information if available (facetDistribution)
-
Federation information for multi-search operations if available (federation)
Contains the following information:
-
An unmodifiable list of
SearchHit<T>objects -
Total hit metadata through
getTotalHits()andgetTotalHitsRelation()-
EQUAL_TO:getTotalHits()is equal to the total matching result set reported by the search engine. -
OFF: exact total-hit metadata is unavailable, sogetTotalHits()is the loaded hit count and is not usable as a page total.
-
-
Execution duration
-
Methods to access individual search hits and check if results exist
The number of returned hits is separate from the reported total hits.
Use getSearchHits().size() for the current result content and use getTotalHits() as exact search total metadata only when getTotalHitsRelation() is EQUAL_TO.
Meilisearch exposes this exact total through paginated search responses; estimated totals and flattened or aggregate responses are reported with OFF.
Queries
The SearchOperations interface methods take different Query parameters that define the query to execute.
Spring Data Meilisearch provides several implementations: BasicQuery, IndexQuery, FacetQuery, and SimilarQuery.
BasicQuery
BasicQuery is the standard implementation for simple search queries:
BasicQuery query = new BasicQuery("Wonder Woman");
IndexQuery
IndexQuery is used for multi-search operations:
List<IndexQuery> queries = List.of(
new IndexQuery("Wonder Woman"),
new IndexQuery("Batman")
);
Search Types
Spring Data Meilisearch supports different types of search operations to accommodate various use cases.
Standard Search
Standard search allows you to search for documents within a single index:
// Search with BasicQuery
BaseQuery query = new BasicQuery("Wonder Woman");
SearchHits<Movie> result = meilisearchOperations.search(query, Movie.class);
List<SearchHit<Movie>> searchHits = result.getSearchHits();
List<Movie> movies = searchHits.stream().map(SearchHit::getContent).toList();
// Search with filter
BaseQuery filterQuery = BasicQuery.builder()
.withFilter(new String[] { "genres = Drama" })
.build();
SearchHits<Movie> filterResult = meilisearchOperations.search(filterQuery, Movie.class);
Multi-Search
Spring Data Meilisearch supports two types of multi-search operations: non-federated and federated multi-search.
Non-Federated Multi-Search
Non-federated multi-search allows you to execute multiple search queries in a single request. This can be done with homogeneous query types, mixed query types, or across multiple indices:
// Multi-search across single indices
List<BaseQuery> queries = List.of(
new BasicQuery("Carol"),
new BasicQuery("Wonder Woman")
);
SearchHits<Movie> singleIndexResults = meilisearchOperations.multiSearch(queries, Movie.class);
// Multi-search across multiple indices
List<BaseQuery> multiIndexQueries = List.of(
IndexQuery.builder().withQ("Carol").withIndexUid("movies").build(),
IndexQuery.builder().withQ("Wonder Woman").withIndexUid("comics").build()
);
SearchHits<Movie> multiIndexResults = meilisearchOperations.multiSearch(multiIndexQueries, Movie.class);
Federated Multi-Search
Federated multi-search allows you to combine and process results from multiple indices using different strategies like merging or joining the results. This is particularly useful when you need to search across multiple indices and want to control how the results are combined:
// Configure federation options
MultiSearchFederation federation = new MultiSearchFederation();
federation.setLimit(20); // Total number of results to return
federation.setOffset(0); // Starting position for results
federation.setMergeFacets(true); // Combine facets from all indices
// Perform federated search across multiple indices
List<BaseQuery> multiIndexQueries = List.of(
IndexQuery.builder().withQ("Wonder Woman").withIndexUid("movies").build(),
IndexQuery.builder().withQ("Wonder Woman").withIndexUid("comics").build()
);
SearchHits<Movie> federatedResults = meilisearchOperations.multiSearch(multiIndexQueries, federation, Movie.class);
The pageable option in query is not supported in federated multi-search.
Instead, use the limit and offset parameters in the federation configuration.
|
While both BasicQuery and IndexQuery can be used for multi-search operations, IndexQuery is required when you need to specify different index UIDs or configure federation options.
Only IndexQuery provides methods like withIndexUid() that allow you to search across multiple indices.
When performing multi-index searches, all results are converted to the specified class type (Movie.class in the example).
If you need to preserve the original types, you should extract and compare specific fields rather than entire objects.
Facet Search
Facet search allows you to retrieve facet information for building faceted navigation interfaces:
// First, ensure the field is set as filterable in the index settings
meilisearchOperations.applySettings(Movie.class);
// Perform facet search
FacetQuery query = new FacetQuery("genres");
SearchHits<FacetHit> result = meilisearchOperations.facetSearch(query, Movie.class);
// Process facet results
result.getSearchHits().forEach(hit -> {
FacetHit facetHit = hit.getContent();
System.out.println("Value: " + facetHit.getValue());
System.out.println("Count: " + facetHit.getCount());
});
Unlike standard and multi-search operations that return entities of type T, facet searches return FacetHit objects containing facet information.
Note that while the clazz parameter still specifies the document type being searched, the return type is always SearchHits<FacetHit> rather than SearchHits<T>.
Similar Documents Search
Similar documents search uses Meilisearch’s Similar Documents API to retrieve documents that are semantically close to a source document. The index must already have a compatible embedder configured in Meilisearch before executing this operation.
SimilarQuery query = SimilarQuery.builder()
.withDocumentId("143")
.withEmbedder("manual")
.withAttributesToRetrieve(new String[] { "title", "description" })
.withFilter("genres = Action")
.withLimit(10)
.withShowRankingScore(true)
.build();
SearchHits<Movie> result = meilisearchOperations.similarSearch(query, Movie.class);
List<Movie> movies = result.getSearchHits().stream()
.map(SearchHit::getContent)
.toList();
documentId and embedder are required. Optional parameters such as limit, offset, filter, ranking-score flags, and vector retrieval are only sent to Meilisearch when explicitly configured on SimilarQuery.