【问题标题】:How to search with wildcards in multiple fields?如何在多个字段中使用通配符进行搜索?
【发布时间】:2015-02-15 16:03:22
【问题描述】:

我正在尝试实现基于休眠搜索的搜索。 我设法根据某些条件组合搜索字段,但在这种情况下,我无法使用通配符进行搜索。

    List<String> spalten = new ArrayList<String>();

    FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
            .getFullTextEntityManager(em);

    QueryBuilder qb = fullTextEntityManager.getSearchFactory()
            .buildQueryBuilder().forEntity(BeitragVO.class).get();

    List<BeitragVO> results;
        // add fields for search
        List<String> fields= new ArrayList<String>();

        if (student) {
            logger.info("hit student");
            spalten.add("user.surname");
            spalten.add("user.givenname");
        }
        if (company) {
            logger.info("hit company");
            spalten.add("company.name");
        }

        for (String string : fields) {
            logger.info(string);
        }
        logger.info("Searchterm:" + searchterm);
        org.apache.lucene.search.Query luceneQuery = qb.keyword()
                .onFields(fields.toArray(new String[fields.size()]))
                .matching(searchterm).createQuery();

        logger.info("Query: " + luceneQuery.toString());

        javax.persistence.Query jpaQuery = fullTextEntityManager
                .createFullTextQuery(luceneQuery, ArticleVO.class);

        results= jpaQuery.getResultList();

在我的搜索输入下,我有六个复选框,用户可以检查或不检查。 如果用户检查学生,则搜索仅适用于学生表。这完全没问题!

问题: 搜索输入:亚历山 (亚历山大)

没有找到结果!

我尝试过这样的通配符搜索:

    TermContext tc = qb.keyword();

    WildcardContext wcc = tc.wildcard();
       if (student) {

            TermMatchingContext tmc = wcc.onField("user.surname");
            tmc = tmc.andField("user.givenname");
            luceneQuery = tmc.matching(searchterm).createQuery();
        }

这是正确的语法,我得到了正确的查询(user.surname:alexander user.givenname:alexander)。但仍然是一个空的结果列表。

我真的很喜欢没有通配符的尝试。有没有办法在这次尝试中添加通配符搜索?

【问题讨论】:

    标签: hibernate wildcard hibernate-search


    【解决方案1】:

    使用通配符“*”应该可以工作。实际上,您需要构建类似的东西:

    qb.keyword()
      .wildcard()
      .onField( "user.givenname" )
      .matching( "Alex*" )
      .createQuery(); 
    

    显然,您需要分解 DSL 以添加一些条件逻辑,但它应该可以工作。您确定您的示例中的“搜索词”添加了通配符吗?

    分解 DSL 的替代方法是创建多个独立查询并通过 BooleanQuery 组合它们。我认为这将更具可读性。

    问题/错误/功能已修复!你可以在这里看到它:

    https://hibernate.atlassian.net/browse/HSEARCH-1811

    【讨论】:

    • 好吧,我的观点是:它确实适用于单个字段(使用 wildcard()),但方法 onFields() 不适用于 wildcard()。 'searchterm' 不包含通配符。即使不是,如果我将 * 添加到该术语中!我考虑过 BooleanQuery,但不知道它们对我的情况有何帮助。
    • 关于 ...wildcard().onFields()... - 我认为这确实是一个错误/缺失的功能。你可以在这里创建一个 JIRA 问题 - hibernate.atlassian.net/browse/HSEARCH。关于布尔查询。检查此示例docs.jboss.org/hibernate/stable/search/reference/en-US/…。您需要做的就是为每个字段创建一个查询并将它们组合起来。最后但并非最不重要的一点是,在您的情况下,'*' 被删除,因为没有通配符(),分析器将删除它。
    • 未来两三个月内是否有机会实现该功能或修复该错误?
    • 不知道。创建问题并从那里解决。如果您想增加它被集成的机会,请提供修复。毕竟它是开源的,总是欢迎贡献:-)
    • 刚刚创建了这个问题,但我并不擅长这个。 :D hibernate.atlassian.net/browse/HSEARCH-1811 你知道,我的意思是,如果它不正确,也许你可以编辑一下。 :-) 谢谢,到目前为止!
    【解决方案2】:

    只有 Alexan 会被假定为完全匹配,请尝试使用 Alexan*

    【讨论】:

    • 我的数据库中有很多 Alexanders 和 Alex 的。只会找到完全匹配的内容。即使使用 。示例:Al = 无结果 Al = 无结果 Alex = 结果
    • 是通配符 lucene 查询期望 * 或 ?字符作为正则表达式
    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 2014-02-05
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多