我正在构建一个包含特殊名称的搜索索引 - 包含!和?和&和+和......我必须进行以下不同的搜索:
me&你
我+你
但无论我做什么(在索引之前尝试使用queryparser转义,手动转义它,尝试不同的索引器......) - 如果我用Luke检查搜索索引它们不会显示(问号和@ -symbols和喜欢出现)
背后的逻辑是我正在部分搜索实时建议(并且字段不是那么大)所以我把它分成“m”和“我”,“+”和“y”和“哟” “和”你“然后索引它(这样它比通配符查询搜索速度快(并且索引大小不是一个大问题)。
所以我需要的是将这个特殊的通配符插入到索引中。
这是我的代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Lucene.Net.Analysis;
using Lucene.Net.Util;
namespace AnalyzerSpike
{
public class CustomAnalyzer : Analyzer
{
public override TokenStream TokenStream(string fieldName, TextReader reader)
{
return new ASCIIFoldingFilter(new LowerCaseFilter(new CustomCharTokenizer(reader)));
}
}
public class CustomCharTokenizer : CharTokenizer
{
public CustomCharTokenizer(TextReader input) : base(input)
{
}
public CustomCharTokenizer(AttributeSource source, TextReader input) : base(source, input)
{
}
public CustomCharTokenizer(AttributeFactory factory, TextReader input) : base(factory, input)
{
}
protected override bool IsTokenChar(char c)
{
return c != ' ';
}
}
}
创建索引的代码:
private void InitIndex(string path, Analyzer analyzer)
{
var writer = new IndexWriter(path, analyzer, true);
//some multiline textbox that contains one item per line:
var all = new List<string>(txtAllAvailable.Text.Replace("\r","").Split('\n'));
foreach (var item in all)
{
writer.AddDocument(GetDocument(item));
}
writer.Optimize();
writer.Close();
}
private static Document GetDocument(string name)
{
var doc = new Document();
doc.Add(new Field(
"name",
DeNormalizeName(name),
Field.Store.YES,
Field.Index.ANALYZED));
doc.Add(new Field(
"raw_name",
name,
Field.Store.YES,
Field.Index.NOT_ANALYZED));
return doc;
}
(代码在Lucene.net版本1.9.x中编辑(编辑:对不起 - 是2.9.x)但与Java中的Lucene兼容)
THX
答案 0 :(得分:0)
终于有时间再次研究它。我的denormalice方法中的一些愚蠢的错误确实过滤掉了单个字符部分(就像它在开头一样),因此如果被空格包围,它会过滤掉加号: - /
通过Moleski来帮助你!
private static string DeNormalizeName(string name)
{
string answer = string.Empty;
var wordsOnly = Regex.Replace(name, "[^\\w0-9 ]+", string.Empty);
var filterText = (name != wordsOnly) ? name + " " + wordsOnly : name;
foreach (var subName in filterText.Split(' '))
{
if (subName.Length >= 1)
{
for (var j = 1; j <= subName.Length; j++)
{
answer += subName.Substring(0, j) + " ";
}
}
}
return answer.TrimEnd();
}