Lucene查询:bla~*(匹配以模糊开头的单词),如何匹配?

Lucene查询:bla~*(匹配以模糊开头的单词),如何匹配?,lucene,wildcard,fuzzy-search,Lucene,Wildcard,Fuzzy Search,在Lucene查询语法中,我希望将*和~组合到一个有效查询中,类似于: bla~*//查询无效 意思:请匹配以“bla”或类似“bla”开头的单词 更新: 我现在所做的工作是使用以下内容(SOLR模式的一部分): 如果您不使用SOLR,则执行以下操作 索引时间:通过创建包含我(短)输入的所有前缀的字段来索引数据 Searchtime:只使用~运算符,因为前缀在索引中显式出现。我不相信Lucene支持这样的操作,也不相信它有一个简单的解决方案 “模糊”搜索不会对固定数量的字符进行操作 BLA

在Lucene查询语法中,我希望将*和~组合到一个有效查询中,类似于: bla~*//查询无效

意思:请匹配以“bla”或类似“bla”开头的单词

更新: 我现在所做的工作是使用以下内容(SOLR模式的一部分):


如果您不使用SOLR,则执行以下操作

索引时间:通过创建包含我(短)输入的所有前缀的字段来索引数据


Searchtime:只使用~运算符,因为前缀在索引中显式出现。

我不相信Lucene支持这样的操作,也不相信它有一个简单的解决方案

“模糊”搜索不会对固定数量的字符进行操作<代码> BLA~可以匹配<代码> BRAH < /代码>,因此必须考虑整个术语。

您可以实现一个查询扩展算法,将查询
bla~*
转换为一系列OR查询

bla* OR blb* OR blc OR .... etc.
但只有当字符串非常短或者可以根据一些规则缩小扩展范围时,这才是可行的

或者,如果前缀的长度是固定的,您可以添加带有子字符串的字段,并对其执行模糊搜索。这将为您提供您想要的,但只有在您的用例足够狭窄的情况下才会起作用

您没有明确说明为什么需要这个,也许这样做会引出其他解决方案

我能想到的一个场景是处理不同形式的单词。例如,查找
汽车
汽车

这在英语中很容易,因为有词干分析器可用。在其他语言中,如果不是不可能的话,实现词干分析器可能相当困难

但是,在这个场景中,您可以(假设您可以访问好的词典)查找搜索词并以编程方式展开搜索以搜索该词的所有形式


例如,搜索
汽车
会转换为
汽车或汽车
。这已经在至少一个搜索引擎中成功地应用于我的语言,但显然很难实现。

您的意思是希望将通配符和模糊查询结合起来?可以将布尔查询与OR条件结合使用,例如:

BooleanQuery bq = new BooleanQuery();

Query q1 = //here goes your wildcard query
bq.Add(q1, BooleanClause...)

Query q2 = //here goes your fuzzy query
bq.Add(q2, BooleanClause...)

这是一个地址搜索服务,我想根据部分输入和可能输入错误的streetnames/citynames/etc(任意组合)来建议地址。(想想ajax,用户在文本字段中键入部分街道地址)

对于这种情况,建议的查询扩展可能不太可行,因为部分字符串(街道地址)可能变得比“short”长:

标准化

我能想到的一种可能性是使用字符串“规范化”,而不是模糊搜索,并简单地将其与通配符查询相结合。地址

“米克拉布拉特42,101雷克雅未克”
,标准化后将变成
“米克拉布拉特42,101雷克雅未克”

那么,像这样建立索引

1) 使用包含街道名称、城市名称等“规范化”版本的记录建立索引,每个文档有一个街道地址(1个或多个字段)

并按如下方式搜索索引:

2) 规范化用于形成查询(即
mik-rek
)的输入字符串(例如
mik-rek
)。 3) 使用通配符op执行搜索(即
mik*和rek*
),保留模糊部分


如果规范化算法足够好的话,这将是可行的:)

在lucene的开发主干中(尚未发布),有代码通过AutomatonQuery支持这样的用例。警告:API可能/将在发布前更改,但它提供了一个想法

以下是您案例的一个示例:

// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such
Term term = new Term("yourfield", "bla~*");

// builds a DFA that accepts all strings within an edit distance of 2 from "bla"
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2);

// concatenate this DFA with another DFA equivalent to the "*" operator
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());

// build a query, search with it to get results.
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);

我不相信这会达到OP的要求,因为它基本上会变成“bar~或bar*”,这与“bar~*”不同,也不会找到(例如“brafoo”。是的,这不是我想要的:)好的,谢谢澄清,我使用了一种方法(用于匹配蛋白质名称等)使用字符串距离,如Smith Waterman、Jaro Winkler等。SimMetrics之类的工具可能会有所帮助。这是我第二次听说SimMetrics,也许是时候让它转一转了:)谢谢,虽然模糊搜索不会对固定数量的字符进行操作,但我的情况是,简单地使用~行不通(字符数差异很大)。我想匹配,例如Sunla和Sundlaugarvegur。当然,如果我能告诉lucene只匹配索引中每个单词的前x个字符,使用~将有效…你需要在这里超越lucene,使用字符串比较算法,如Levenstein、Jaro Winkler等(下面的问题)我刚刚回到这个问题,又看到了你的答案。你试过了吗?我现在要做的(适用于小输入),是生成输入的所有前缀,并将前缀放入索引中。然后我只需要使用~运算符,就可以获得像~*这样的功能。对于小的输入,您的解决方法很好。。。但正如你所暗示的,对于大量输入来说,这将是一个问题:你将为所有这些前缀添加大量的术语和帖子。。。这将使Lucene 4.0之前的模糊查询变得更慢,因为它会对所有术语进行线性扫描。是否有Lucene查询语法允许您通过Solr访问自动机查询而无需编码?
// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such
Term term = new Term("yourfield", "bla~*");

// builds a DFA that accepts all strings within an edit distance of 2 from "bla"
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2);

// concatenate this DFA with another DFA equivalent to the "*" operator
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());

// build a query, search with it to get results.
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);