Search code examples
javaspringhibernatespring-data-jpalucene

Hibernate lucene search in one OneToMany object only


I have object Document with bidirectional OneToMany mapping to Metadata. I would like to search with Hibernate search with Licene for multiple wildcard queries, but matching only in Documents, where at least one Metadata object in metadataSet.value contains all wildcard queries. In example it should work like this. I have two documents: Document1

{
"metadataSet": [
   {"value": "my value"},
   {"value": "new value"}
   ]
}

Document2

{
"metadataSet": [
   {"value": "my"},
   {"value": "value"}
   ]
}

For keywords "my" and "val" it should find match only in Document1, because it has at least one metadataSet.value containing both wildcards.

The problem is, that now I am matching both documents. Because Document2 has values matching both wildcards. My incorrectly working query is this:

// keywords = List.of("*my*", "*val*")
searchSession.search(Document.class)
  .where(f -> f.bool(b -> {
      for(String keyword : keywords){
         b.should(f.wildcard().field("metadataSet.value").matching(keyword));}}));

My lucene config:

public class LuceneSearchConfiguration implements LuceneAnalysisConfigurer {
  @Override
  public void configure(LuceneAnalysisConfigurationContext context) {
    context.analyzer("autocomplete_indexing").custom()
        .tokenizer(WhitespaceTokenizerFactory.class)
        .tokenFilter(LowerCaseFilterFactory.class);
    context.analyzer("autocomplete_search").custom()
        .tokenizer(WhitespaceTokenizerFactory.class)
        .tokenFilter(LowerCaseFilterFactory.class);
  }
}

My objects:

@Entity
@Indexed
@Table(name = "documents")
public class Document{

  @IndexedEmbedded
  @OneToMany(mappedBy = "document")
  private Set<Metadata> metadataSet = new HashSet<>();
...
}

@Entity
@Indexed
@Table(name = "metadata")
public class Metadata{

  @ManyToOne
  @JoinColumn(name = "document_id")
  private Document document;

  @FullTextField(analyzer = "autocomplete_indexing", searchAnalyzer = "autocomplete_search")
  @Column(name = "value")
  private String value;
...
}

Solution

  • I did find a solution. A solution is to use nested indexing.