正则表达式将带连字符的单词与无连字符查询匹配
Regex match hyphenated word with hyphen-less query
我有一个 Azure 存储 Table 设置,它拥有大量包含连字符、撇号和其他 Azure 索引器不喜欢的标点符号的值。 Hyphenated-Word
在索引时被分成两个标记——Hyphenated
和 Word
。因此,这意味着搜索 HyphenatedWord
不会产生任何结果,无论是否有任何通配符或模糊匹配字符。也就是说,Azure 认知搜索支持 Regex Lucene 查询...
因此,我试图找出是否有正则表达式模式可用于将带或不带连字符的单词与给定查询匹配。例如,查询 homework
应该匹配结果 homework
and home-work
.
我知道,如果我尝试做相反的事情——即使在查询中提供连字符时也匹配未连字符的词——我会使用类似 /home(-)?work/
的东西。但是,我不确定逆函数是什么样子的——如果存在的话。
是否有原始正则表达式模式可以执行我提议的那种匹配?或者我是 SOL?
编辑:我应该指出,我提供的例子是不现实的,因为我并不总是知道连字符应该在哪里.最理想的情况是,执行此匹配的模式与连字符的精确位置无关。
编辑 2:我发现有效但不完全最佳[=39]的解决方案=](虽然我没有办法证明这一点,但可能不是 performant)只是分解查询,删除所有导致令牌中断的特殊字符,并且然后动态构建一个正则表达式查询,该查询在查询中的每个字符之间都有一个可选的匹配项。使用 homework
示例,该模式看起来像 [-'\.! ]?h[-'\.! ]?o[-'\.! ]?m[-'\.! ]?e[-'\.! ]?w[-'\.! ]?o[-'\.! ]?r[-'\.! ]?k[-'\.! ]?
...这可能是我见过的最丑陋的东西。尽管如此,它还是完成了工作。
听起来您想定义自己的标记化。使用自定义分词器会有帮助吗? https://docs.microsoft.com/azure/search/index-add-custom-analyzers
我对这种情况的解决方案总是引入内容和查询处理。
当您通过 SDK 使用推送模型时,内容处理会更容易,但您可以通过创建 table 的 shadow/copy 来实现相同的目的,其中内容是出于索引目的而被操纵的。你让你原来的 table 完好无损。然后你在处理你的文本的地方维护一个副本table。
查询处理无论如何都应该使用。在最简单的形式中,您希望在查询中使用之前清除最终用户的输入。额外的步骤可以是处理特殊字符,如连字符。根据您的要求转义、剥离或进行其他操作。
示例
我必须支持搜索可能包含连字符或其他特殊字符的订购代码。我们订购代码的维护者可能会以不一致的格式定义订购代码。访问我们网站的客户同样不一致。
要求是ABC-123-DE_F-4.56G要匹配
中的任意一个
- ABC-123-DE_F-4.56G
- ABC123-DE_F-4.56G
- ABC_123_DE_F_4_56G
- ABC.123.DE.F.4.56G
- ABC 123 DEF 56 G
- ABC123DEF56G
我使用上面建议的方法解决了这个问题。我使用内容处理来生成没有任何特殊字符的订购代码版本(使用简单的正则表达式)。然后,我使用查询处理将最终用户的输入转换为 OR 查询,例如:
<verbatim-user-input-cleaned> OR OrderCodeVariation:<verbatim-user-input-without-special-chars>
所以,如果用户输入 ABC.123.DE.F.4.56G 我会有效地搜索
ABC.123.DE.F.4.56G OR OrderingCodeVariation:ABC123DEF56G
要添加到 Jennifer 的答案中,您可以考虑使用由以下任一标记过滤器组成的自定义分析器:
- pattern_replace:一个标记过滤器,它将模式应用于流中的每个标记,用指定的替换字符串替换匹配项。
- pattern_capture:使用 Java 正则表达式发出多个标记,一个用于一个或多个模式中的每个捕获组。
您可以使用 pattern_replace 标记过滤器将连字符替换为所需字符,可能是空字符。
我有一个 Azure 存储 Table 设置,它拥有大量包含连字符、撇号和其他 Azure 索引器不喜欢的标点符号的值。 Hyphenated-Word
在索引时被分成两个标记——Hyphenated
和 Word
。因此,这意味着搜索 HyphenatedWord
不会产生任何结果,无论是否有任何通配符或模糊匹配字符。也就是说,Azure 认知搜索支持 Regex Lucene 查询...
因此,我试图找出是否有正则表达式模式可用于将带或不带连字符的单词与给定查询匹配。例如,查询 homework
应该匹配结果 homework
and home-work
.
我知道,如果我尝试做相反的事情——即使在查询中提供连字符时也匹配未连字符的词——我会使用类似 /home(-)?work/
的东西。但是,我不确定逆函数是什么样子的——如果存在的话。
是否有原始正则表达式模式可以执行我提议的那种匹配?或者我是 SOL?
编辑:我应该指出,我提供的例子是不现实的,因为我并不总是知道连字符应该在哪里.最理想的情况是,执行此匹配的模式与连字符的精确位置无关。
编辑 2:我发现有效但不完全最佳[=39]的解决方案=](虽然我没有办法证明这一点,但可能不是 performant)只是分解查询,删除所有导致令牌中断的特殊字符,并且然后动态构建一个正则表达式查询,该查询在查询中的每个字符之间都有一个可选的匹配项。使用 homework
示例,该模式看起来像 [-'\.! ]?h[-'\.! ]?o[-'\.! ]?m[-'\.! ]?e[-'\.! ]?w[-'\.! ]?o[-'\.! ]?r[-'\.! ]?k[-'\.! ]?
...这可能是我见过的最丑陋的东西。尽管如此,它还是完成了工作。
听起来您想定义自己的标记化。使用自定义分词器会有帮助吗? https://docs.microsoft.com/azure/search/index-add-custom-analyzers
我对这种情况的解决方案总是引入内容和查询处理。
当您通过 SDK 使用推送模型时,内容处理会更容易,但您可以通过创建 table 的 shadow/copy 来实现相同的目的,其中内容是出于索引目的而被操纵的。你让你原来的 table 完好无损。然后你在处理你的文本的地方维护一个副本table。
查询处理无论如何都应该使用。在最简单的形式中,您希望在查询中使用之前清除最终用户的输入。额外的步骤可以是处理特殊字符,如连字符。根据您的要求转义、剥离或进行其他操作。
示例
我必须支持搜索可能包含连字符或其他特殊字符的订购代码。我们订购代码的维护者可能会以不一致的格式定义订购代码。访问我们网站的客户同样不一致。
要求是ABC-123-DE_F-4.56G要匹配
中的任意一个- ABC-123-DE_F-4.56G
- ABC123-DE_F-4.56G
- ABC_123_DE_F_4_56G
- ABC.123.DE.F.4.56G
- ABC 123 DEF 56 G
- ABC123DEF56G
我使用上面建议的方法解决了这个问题。我使用内容处理来生成没有任何特殊字符的订购代码版本(使用简单的正则表达式)。然后,我使用查询处理将最终用户的输入转换为 OR 查询,例如:
<verbatim-user-input-cleaned> OR OrderCodeVariation:<verbatim-user-input-without-special-chars>
所以,如果用户输入 ABC.123.DE.F.4.56G 我会有效地搜索
ABC.123.DE.F.4.56G OR OrderingCodeVariation:ABC123DEF56G
要添加到 Jennifer 的答案中,您可以考虑使用由以下任一标记过滤器组成的自定义分析器:
- pattern_replace:一个标记过滤器,它将模式应用于流中的每个标记,用指定的替换字符串替换匹配项。
- pattern_capture:使用 Java 正则表达式发出多个标记,一个用于一个或多个模式中的每个捕获组。
您可以使用 pattern_replace 标记过滤器将连字符替换为所需字符,可能是空字符。