استفاده از لوسین برای برجسته سازی عبارت جستجو شده در نتایج حاصل
نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۴/۲۷ ۱۲:۳۸
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
public class Post
{
public int Id { set; get; }
public string Title { set; get; }
public string Body { set; get; }
}
static Document MapPostToDocument(Post post)
{
var postDocument = new Document();
postDocument.Add(new Field("Id", post.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
postDocument.Add(new Field("Title", post.Title, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
postDocument.Add(new Field("Body", post.Body, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
return postDocument;
}
public static string RemoveHtmlTags(string text)
{
return string.IsNullOrEmpty(text) ? string.Empty : Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
}
static readonly Lucene.Net.Util.Version _version = Lucene.Net.Util.Version.LUCENE_29;
public static void CreateIdx(IEnumerable<Post> dataList)
{
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
var analyzer = new StandardAnalyzer(_version);
using (var writer = new IndexWriter(directory, analyzer, create: true, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
foreach (var post in dataList)
{
writer.AddDocument(MapPostToDocument(post));
}
writer.Optimize();
writer.Commit();
writer.Close();
directory.Close();
}
}
public static void UpdateIndex(Post post)
{
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
var analyzer = new StandardAnalyzer(_version);
using (var indexWriter = new IndexWriter(directory, analyzer, create: false, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
var newDoc = MapPostToDocument(post);
indexWriter.UpdateDocument(new Term("Id", post.Id.ToString()), newDoc);
indexWriter.Commit();
indexWriter.Close();
directory.Close();
}
}
public static void DeleteIndex(Post post)
{
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
var analyzer = new StandardAnalyzer(_version);
using (var indexWriter = new IndexWriter(directory, analyzer, create: false, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
indexWriter.DeleteDocuments(new Term("Id", post.Id.ToString()));
indexWriter.Commit();
indexWriter.Close();
directory.Close();
}
}
public static void AddIndex(Post post)
{
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
var analyzer = new StandardAnalyzer(_version, getStopWords());
using (var indexWriter = new IndexWriter(directory, analyzer, create: false, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
var searchQuery = new TermQuery(new Term("Id", post.Id.ToString()));
indexWriter.DeleteDocuments(searchQuery);
var newDoc = MapPostToDocument(post);
indexWriter.AddDocument(newDoc);
indexWriter.Commit();
indexWriter.Close();
directory.Close();
}
}
public static void Query(string term)
{
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
using (var searcher = new IndexSearcher(directory, readOnly: true))
{
var analyzer = new StandardAnalyzer(_version);
var parser = new MultiFieldQueryParser(_version, new[] { "Body", "Title" }, analyzer);
var query = parseQuery(term, parser);
var hits = searcher.Search(query, 10).ScoreDocs;
if (hits.Length == 0)
{
term = searchByPartialWords(term);
query = parseQuery(term, parser);
hits = searcher.Search(query, 10).ScoreDocs;
}
FastVectorHighlighter fvHighlighter = new FastVectorHighlighter(true, true);
foreach (var scoreDoc in hits)
{
var doc = searcher.Doc(scoreDoc.doc);
string bestfragment = fvHighlighter.GetBestFragment(
fvHighlighter.GetFieldQuery(query),
searcher.GetIndexReader(),
docId: scoreDoc.doc,
fieldName: "Body",
fragCharSize: 400);
var id = doc.Get("Id");
var title = doc.Get("Title");
var score = scoreDoc.score;
Console.WriteLine(bestfragment);
}
searcher.Close();
directory.Close();
}
}
private static Query parseQuery(string searchQuery, QueryParser parser)
{
Query query;
try
{
query = parser.Parse(searchQuery.Trim());
}
catch (ParseException)
{
query = parser.Parse(QueryParser.Escape(searchQuery.Trim()));
}
return query;
}
private static string searchByPartialWords(string bodyTerm)
{
bodyTerm = bodyTerm.Replace("*", "").Replace("?", "");
var terms = bodyTerm.Trim().Replace("-", " ").Split(' ')
.Where(x => !string.IsNullOrEmpty(x))
.Select(x => x.Trim() + "*");
bodyTerm = string.Join(" ", terms);
return bodyTerm;
}
var id = doc.Get("Id");
searcher.Search(query, 10)
"برای این موارد متداول از تاریخ تا تاریخ، از همان SQL معمولی استفاده کنید "منظورتون اینه که تو جستجوهای پیشرفته باید از روش معمول و like(یعنی بدون استفاده از full text search و lucene)استفاده بشه؟
سلام؛
من تازه mvc رو شروع کردم در پروژه ای نیاز به استفاده از لوسین دارم خواهش میکنم یک نمونه برنامه که با استفاده از لوسین میباشد را در سایت قرار دهیدبا تشکر
var prop = doc.Get("prop_name");
با سلام
من میخوام توی lucene از عبارات منطقی and و or استفاده کنم ولی هرچی تست میکنم جواب دقیق و کاملی نمیگیرم (جستجو انجام میشه ولی مثلا از 3 آیتمی که حتما باید برگردونه 2 تاشو بر میگردونه).
آیا عبارات منطقی رو میشه در lucene استفاده کرد؟
using (var indexWriter = new IndexWriter(_directory, analyzer, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
no segments* file found in Lucene.Net.Store.SimpleFSDirectory@E:\\Lucene_Index lockFactory=Lucene.Net.Store.NativeFSLockFactory: files: write.lock
private static FSDirectory _directoryTemp;
private static FSDirectory _directory
{
get
{
if (_directoryTemp == null)
_directoryTemp = FSDirectory.Open(new DirectoryInfo(_luceneDir));
if (IndexWriter.IsLocked(_directoryTemp))
IndexWriter.Unlock(_directoryTemp);
string lockFilePath = Path.Combine(_luceneDir, "write.lock");
if (File.Exists(lockFilePath))
File.Delete(lockFilePath);
return _directoryTemp;
}
} private static FSDirectory _shopDirectory;
private static FSDirectory ShopDirectory
{
get
{
if (_shopDirectory == null)
_shopDirectory = FSDirectory.Open(new DirectoryInfo(ShopPath));
if (IndexWriter.IsLocked(_shopDirectory))
IndexWriter.Unlock(_shopDirectory);
var lockFilePath = Path.Combine(ShopPath, "write.lock");
if (File.Exists(lockFilePath))
File.Delete(lockFilePath);
return _shopDirectory;
}
} public static void CreateProducSkustIndex(List<ProductSkuLuceneViewModel> productSkuLucenes)
{
var directory = ShopDirectory;
var analyzer = new StandardAnalyzer(_version, PersianStopwords.List);
using (var writer = new IndexWriter(directory, analyzer, create: true, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
productSkuLucenes.ForEach(row => writer.AddDocument(MapProductToDocument(row)));
writer.Optimize();
writer.Commit();
writer.Close();
}
} public static void CreateProducCategoriestIndex(List<CategoryLuceneViewModel> categoryLucenes)
{
var directory = ShopDirectory;
var analyzer = new StandardAnalyzer(_version, PersianStopwords.List);
using (var writer = new IndexWriter(directory, analyzer, create: true, mfl: IndexWriter.MaxFieldLength.UNLIMITED))
{
categoryLucenes.ForEach(row => writer.AddDocument(MapProductCategoryToDocument(row)));
writer.Optimize();
writer.Commit();
writer.Close();
}
}