如何在hibernate搜索中搜索特殊字符?

时间:2017-10-04 11:38:50

标签: lucene hibernate-search

我是hibernate lucene搜索的新手。从病房的几天开始,我正在研究带有特殊字符的搜索关键字。我正在使用 MultiFieldQueryParser 进行精确的词组匹配以及布尔搜索。但在这个过程中,我无法通过搜索关键字获得结果,例如“拥有1年多的经验”,如果我没有在搜索关键字周围添加任何引号,那么我就会得到结果。所以我在执行lucene查询时观察到的是,它是转义特殊符号(+)。我正在使用StandardAnalyzer.class。我想,如果我使用的是WhiteSpaceAnalyzer,它将无法转义特殊字符,但它可能会影响布尔搜索,如+ java + php(即java和php),因为它可能会视为普通文本。所以请提供一些建议。

以下是我的代码:

Session session = getSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);

        MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[] { "student.skills.skill",
                "studentProfileSummary.profileTitle", "studentProfileSummary.currentDesignation" },
                new StandardAnalyzer());
        parser.setDefaultOperator(Operator.OR);
        org.apache.lucene.search.Query luceneQuery = null;
        QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Student.class).get();
        BooleanQuery boolQuery = new BooleanQuery();
        if (StringUtils.isEmpty(zipcode) != true && StringUtils.isBlank(zipcode) != true) {
            boolQuery.add(
                    qb.keyword().onField("personal.locations.postalCode").matching(zipcode).createQuery(),
                    BooleanClause.Occur.MUST);
        }
        if (StringUtils.isEmpty(query) != true && StringUtils.isBlank(query) != true) {
            try {
                luceneQuery = parser.parse(query.toUpperCase());
            } catch (ParseException e) {
                luceneQuery = parser.parse(parser.escape(query.toUpperCase()));
            }
            boolQuery.add(luceneQuery, BooleanClause.Occur.MUST);
        }
        boolQuery.add(qb.keyword().onField("vStatus").matching(1).createQuery(), BooleanClause.Occur.MUST);
        boolQuery.add(qb.keyword().onField("status").matching(1).createQuery(), BooleanClause.Occur.MUST);
        boolQuery.add(qb.range().onField("studentProfileSummary.profilePercentage").from(80).to(100).createQuery(),
                BooleanClause.Occur.MUST);
        FullTextQuery createFullTextQuery = fullTextSession.createFullTextQuery(boolQuery, Student.class);
        createFullTextQuery.setProjection("id", "studentProfileSummary.profileTitle", "firstName","lastName");

        if (isEmptyFilter == false) {
            createFullTextQuery.setFirstResult((int) pageNumber);
            createFullTextQuery.setMaxResults((int) end);
        }
        return createFullTextQuery.list();

1 个答案:

答案 0 :(得分:1)

控制此类效果的关键在于您选择使用的分析仪。正如您所注意到的那样,标准分析器将删除/忽略一些符号,因为它们通常不被使用。

由于标准分析器适用于大多数英语自然语言,但您想要处理特殊符号,典型的解决方案是将文本索引到多个字段,并为每个字段分配不同的Analyzer。然后,您可以生成针对这两个字段的查询,并合并从两个字段获取的分数。您甚至可以自定义每个字段所具有的权重,并尝试使用不同的Similarity实现来获得各种效果。

但是,不是你的“1年以上”的具体例子,你可能想要考虑你期望它找到什么。它应该匹配“6年”的字符串吗? 然后你可能想要实现一个自定义分析器,专门寻找这样的模式并生成多个匹配的令牌,如序列{“1年”,“2年”,“3年”,......}。这将是有效的,但只能匹配特定的术语序列,所以您可能希望从Lucene社区中寻找更高级的扩展,因为您可以在其中插入更多的扩展。