我有以下查询,可以通过全名搜索特定医疗中心的患者:
MustJunction mj = qb.bool().must(qb.keyword()
.onField("medicalCenter.id")
.matching(medicalCenter.getId())
.createQuery());
for(String term: terms)
if(!term.equals(""))
mj.must(qb.keyword()
.onField("fullName")
.matching(term+"*")
.createQuery());
并且它运行良好,但前提是用户键入患者的完整姓氏和/或姓氏。
但是,即使用户键入 了 名字或姓氏 的一部分 ,我也想使它工作。
例如,如果有一个叫“ Bilbo Baggins”的患者,当用户键入“ Bilbo Baggins”,“ Bilbo”,“ Baggins”,
或者即使他仅键入“ Bil”或“ Bag”* 时,我希望通过搜索找到他 *
为此,我将上述查询修改如下:
MustJunction mj = qb.bool().must(qb.keyword()
.onField("medicalCenter.id")
.matching(medicalCenter.getId())
.createQuery());
for(String term: terms)
if(!term.equals(""))
mj.must(qb.keyword()
.wildcard()
.onField("fullName")
.matching(term+"*")
.createQuery());
但是,这会中断搜索并且不返回结果。我究竟做错了什么?
简短答案:请勿使用通配符查询,请使用带有的自定义分析器EdgeNGramFilterFactory
。另外,不要尝试自己分析查询(这就是通过将查询分为术语来完成的):Lucene会做得更好(特别是使用WhitespaceTokenizerFactory
,an
ASCIIFoldingFilterFactory
和a LowercaseFilterFactory
)。
长答案:
通配符查询作为解决一次性问题的快速简便的方法很有用,但通配符不是很灵活,可以很快达到其极限。特别是,如@femtoRgon所述,不会对这些查询进行分析,因此,例如,大写查询将不匹配小写名称。
解决Lucene世界中大多数问题的经典解决方案是在索引时间和查询时间(不一定相同)使用特制的分析器。在您的情况下,您将需要在建立索引时使用这种分析器:
@AnalyzerDef(name = "edgeNgram",
tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = ASCIIFoldingFilterFactory.class), // Replace accented characeters by their simpler counterpart (è => e, etc.)
@TokenFilterDef(factory = LowerCaseFilterFactory.class), // Lowercase all characters
@TokenFilterDef(
factory = EdgeNGramFilterFactory.class, // Generate prefix tokens
params = {
@Parameter(name = "minGramSize", value = "1"),
@Parameter(name = "maxGramSize", value = "10")
}
)
})
这种查询时:
@AnalyzerDef(name = "edgeNGram_query",
tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
filters = {
@TokenFilterDef(factory = ASCIIFoldingFilterFactory.class), // Replace accented characeters by their simpler counterpart (è => e, etc.)
@TokenFilterDef(factory = LowerCaseFilterFactory.class) // Lowercase all characters
})
索引分析器会将“ Mauricio Ubilla Carvajal”转换为以下令牌列表:
然后查询分析器会将查询“ mau UB”转换为[“ mau”,“ ub”],这将与索引名称匹配(两个令牌都存在于索引中)。
请注意,您显然必须将分析器分配给该字段。对于索引部分,它是使用@Analyzer
注释完成的。对于查询部分,你将不得不使用overridesForField
的查询生成器如图所示在这里:
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Hospital.class)
.overridesForField( "name", "edgeNGram_query" )
.get();
// Then it's business as usual
还要注意,在Hibernate Search 5中,只有在将它们实际分配给索引的情况下,Elasticsearch分析器定义才由Hibernate
Search生成。因此,默认情况下不会生成查询分析器定义,Elasticsearch将抱怨它不知道分析器。这是一种解决方法:https :
//discourse.hibernate.org/t/cannot-find-the-overridden-analyzer-when-using-
overridesforfield/1043/4?u=yrodiere
我正在用Java Swing制作一个游戏,其中有一个大POJO用来存储游戏的运行时数据,比如精灵的位置、当前显示的效果等等。我希望能够将其作为JSON保存到一个文件中,然后在以后重新构建。我发现Gson应该就是这么做的,但到目前为止我还没能让它工作。我总是遇到这样一个问题:它无法使嵌套在存储类中的某些变量可访问。 以下是我目前使用Gson的方式: 以下是我当前尝试使用时收到的错误消息: 是我在开头
我正在用Java Swing制作一个游戏,其中有一个大POJO用来存储游戏的运行时数据,比如精灵的位置、当前显示的效果等等。我希望能够将其作为Json保存到一个文件中,然后在以后重新构建。我发现Gson应该就是这么做的,但到目前为止我还没能让它工作。我总是遇到这样一个问题:它无法使嵌套在存储类中的某些变量可访问 以下是我目前使用Gson的方式: 这是当我尝试使用时,我当前收到的错误消息: 是我一开
这是我的简单代码 这条线呢 重定向到taskOKAction,但它只允许我通过URL发送参数(?task=123)。 我需要将object$task发送到taskOKAction,以便在屏幕上打印用户在表单中键入的内容。 我该怎么做?在询问好的解决方案是存储表单中的数据(例如,在数据库或文件中)并只在URL中传递对象ID的参数之前,我已经对stackoverflow发了火。我认为这是一个很好的解决
我正在尝试创建一个CXF肥皂Web服务客户端,以便使用经过Kerberos身份验证的SharePoint实例进行肥皂调用。 我导入以下内容: 组织。阿帕奇。cxf:cxf rt前端jaxws:3.2.6 组织。阿帕奇。cxf:cxf rt传输http:3.2.6 组织。阿帕奇。cxf:cxf rt传输http hc:3.2.6 组织。阿帕奇。cxf:cxf rt ws-security:3.2.6
问题内容: 我只想检索UserAccount类中的某些列,所以我有以下代码: 我得到了空值作为回报。但是,如果我注释掉setProjections,我将获得具有所有属性的用户。在这种情况下,如何正确使用setProjection? 问题答案: 它返回一个Object数组,因此代码应为:
问题内容: 我不知道我在哪里错了:/。当我运行这段代码时,我得到的只是一个空白元素。我似乎无法让insertRule方法执行任何操作(甚至不会产生错误)。我想念什么吗? 问题答案: 这有点令人困惑,但是您的代码确实可以工作,只是您看不到返回的XML树中插入的规则。 为了验证您的代码是否有效,您可以执行两个测试: 运行上面的代码片段,您可以看到CSS规则确实适用。并且属性也在控制台中更改。 当浏览器