1

如何配置 lucene + hibernate 并开发通过该字段值的任何确切部分匹配某个字段的通配符查询?例如,如果我们对某个字段“标题”进行了索引,并且它只有两个条目:“我的第一个通配符查询”。和“我的第二个通配符查询。”;那么如果我们查询“irsT WiLdCaRd q”,那么它必须只返回第一个。它也不必区分大小写。

我试过这样的事情:

    FullTextSession ftSession = org.hibernate.search.Search.getFullTextSession((Session) em.getDelegate());
    QueryContextBuilder qbc = ftSession.getSearchFactory().buildQueryBuilder();
    EntityContext entityContext = qbc.forEntity(Book.class);
    QueryBuilder qb = entityContext.get();
    org.apache.lucene.search.Query q = qb.keyword().wildcard().onField("title")
            .ignoreAnalyzer().matching("*" + QueryParser.escape("irsT WiLdCaRd q").toLowerCase() + "*").createQuery();
    FullTextEntityManager ftEm = org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
    final FullTextQuery ftq = ftEm.createFullTextQuery(q, Book.class);
    List list = ftq.getResultList();

并且它不起作用,因为它是面向关键字的,并且没有用于短语的通配符的类比。使用直接 WildcardQuery 也不起作用(

4

1 回答 1

4

Lucene 不支持短语查询中的通配符。关于如何在索引中表示数据的策略可以让您完成它。

您正在将查询视为关键字,它会出现。在这种情况下,您应该在索引时真正将字段视为关键字,在这种情况下,您可以将整个标题作为单个词进行搜索。带有空格的短语和关键字与 Lucene 非常不同,您不能互换使用它们。

但是,更好的解决方案可能是依靠评分来为一组术语查询提供最佳匹配。如果您仅使用标准分析器将您指示的查询减少为一组三个术语:*irsT WiLdCaRdand q*,虽然您指示的两个术语都会被找到,但您想要的术语将首先返回,并且得分明显更高。您可以在某种程度上磨练可接受的找到的文档,使用所需的术语进行搜索,例如: +title:*irsT +title:WiLdCaRd +title:q*. 这将消除任何不包含所有三个术语的匹配项,尽管它们的顺序或其他术语的存在不会阻止匹配。

另外,另一个注意事项:*irst除非您将其设置为启用前导通配符,否则不允许查询。如果可以避免,通常不鼓励这样做。使用前导通配符进行搜索可能会非常慢,除非您已经为它们优化了索引(例如,参见 SOLR 的ReversedWildcardFilterFactory)。

于 2013-01-09T16:41:27.787 回答