我有一个可以通过SolR上的url查询执行搜索的webapp。
结果作为Document对象接收。
我的查询看起来像:q=Book:Harlan AND Book:Coben AND ..
,它运行正常。
String[] word = searchedWord.trim().split(" ");
for (int i = 0; i < word.length; i++) {
if (!StringUtils.isEmpty(word[i])) {
if (i > 0) {
query.append("%20AND%20");
}
String utf_encoded = URLEncoder.encode(StringEscapeUtils.escapeJava(word[i]), "UTF-8");
}
}
但我需要强制执行搜索条件,因为当搜索的字词与确切的字词"Harlan Coben"
完全相同时,此代码会将其分为两个字"Harlan
和Coben"
< / p>
例如,我的webapp应该能够搜索:
确切条款:"Harlan Coben"
多个术语:shakespeare harlan coben
多个混合字词:shakespeare "harlan coben" coben
或shakespear "harlan coben"
或"harlan coben" coben
调用SolR的URL以UTF-8编码,以替换特殊字符..
我该怎么办?通过正则表达式?还是有另一种方式?
------编辑--------
更具体一点,所有这些字符都可以是“@(!ùéàç”或中文/俄文或其他任何字符(unicode?)来自特定语言。
我需要匹配它们并将它们分开以准备SolR查询。
示例:
如果搜索字词为:coben "Harlan Coben" s(554603)hakesdpeare Straße Привет
我的正则表达式应该匹配并给我这个结果:
coben
"Harlan Coben"
s(554603)hakesdpeare
Straße
Привет
然后我需要使用AND Book:
或juste Book:
将它们连接起来,以获得如下查询:
q=Book:coben AND Book:"Harlan Coben" AND Book:s(554603)hakesdpeare AND Book:Straße AND Book:Привет
我从@fge尝试("[a-z]+(?:\s+[a-z]+)+"|[a-z]+)(?:\s+|$)
(感谢您),但它只与[a-z]匹配,我尝试使用\\p{all}
但是没有效果..
有什么想法吗?
------结束编辑--------
感谢您的帮助!
答案 0 :(得分:1)
你可以使用正则表达式,但它会非常复杂;在这种情况下,您需要更改。这里假设您的搜索字词只有字母:
("[a-z]+(?:\s+[a-z]+)+"|[a-z]+)(?:\s+|$)
(请注意,交替顺序重要在这里!)
示例:
public final class Bar
{
private static final Pattern PATTERN = Pattern
.compile("(\"[a-z]+(?:\\s+[a-z]+)+\"|[a-z]+)(?:\\s+|$)",
Pattern.CASE_INSENSITIVE);
public static void main(final String... args)
throws IOException
{
tryAndMatch("\"Harlan Coben\"");
tryAndMatch("shakespeare harlan coben");
tryAndMatch("shakespeare \"harlan coben\" coben");
}
private static void tryAndMatch(final String input)
{
final Matcher m = PATTERN.matcher(input);
System.out.printf("INPUT: -->%s<--\n", input);
while (m.find())
System.out.printf("Term -->%s<--\n", m.group(1));
System.out.println("END INPUT");
}
}
现在,关于替换为网址,请注意URLEncoder
是而不是对网址组件进行编码,它会对application/x-www-form-urlencoded
数据进行编码,其中包含空格变为+
并且没有与URI路径或片段相同的转义字符集。
最准确的解决方案是使用URI模板。这允许您编写模板,例如:
http://my.site/?q={query}
其中query
是任何Unicode字符串,这将为您编码(自我推销:如果您感兴趣,我有一个library to do that)。
第二种是使用Guava 15.0+,它有一个set of escapers especially made for URLs。
答案 1 :(得分:0)
我终于找到了正确的正则表达式来匹配任何字符(包括中文或其他语言)并给我每个搜索词:
搜索示例如下:
harlan coben“harlan coben”
找到的每个匹配将是:
哈朗
coben
“哈伦科本”
以下是使用过的代码:
Pattern PATTERN = Pattern.compile("(?>\"[^\"]+\"+)|(?>[^ ]+)+");
Matcher match = PATTERN.matcher(motRecherche);
match.reset();
int iM = 0;
while(match.find()){
if(iM > 0){
query.append("%20AND%20");
}
String utf_encoded = CommonUtils.escapeSolrQuery(match.group(0));
query.append(":"+utf_encoded);
iM++;
}
关于SolR的另一件事,它需要逃避一些特殊字符 + - &amp;&amp; || ! (){} [] ^“〜*?:\ ,SolR提供了一个名为ClientUtils的客户端类和一个我为我改变的方法escapeQueryChars():
public static String escapeSolrQuery(String searchWord){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < searchWord.length(); i++) {
char c = searchWord.charAt(i);
if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
|| c == '^' || c == '[' || c == ']' || c == '{' || c == '}' || c == '~'
|| c == '*' || c == '?' || c == '|' || c == '&' || c == ';' || c == '/')
{
sb.append('\\');
}
if(c == '\"' && !searchWord.matches("\"[^\"]+\"")){
sb.append('\\');
}
sb.append(c);
}
return sb.toString();
}
现在它可以正常工作:)