หลังจากทำงานหนักมาหลายวัน ในที่สุดฉันก็ใช้การค้นหาข้อความแบบเต็มแบบง่ายๆ ให้ฉันทบทวนและสรุป
บทความนี้ Lucene.Net ทำอะไรได้บ้าง? และคำถามว่าจะทำอย่างไร? ในที่สุด ก็มีตัวอย่างของ Lucene.Net ที่ใช้การค้นหาข้อความแบบเต็ม
1. Lucene.Net คืออะไร?
เดิมที Lucene.net นั้นเป็นโครงการโอเพ่นซอร์สและจากนั้นก็หันไปสู่เชิงพาณิชย์ Lucene.net 2.0 ก็เปิดตัวเช่นกัน แต่เพื่อเงิน D. ชะตากรรมของ Lucene.net ค่อนข้างคล้ายกับ FreeTextBox ซึ่งเริ่มต้นด้วย 2.0 เปิดตัวหลังเวอร์ชัน 1.6 5. เส้นทางเชิงพาณิชย์ 2.0 มีเวอร์ชันฟรีในรูปแบบของ DLL และเวอร์ชันซอร์สโค้ดจะต้องซื้อใบอนุญาตเชิงพาณิชย์ อย่างไรก็ตาม จะปล่อยให้ซอร์สโค้ดเวอร์ชัน 1.6.5 ออกไป และคุณยังคงสามารถดูรายละเอียดภายในส่วนใหญ่ได้ แต่ในเวอร์ชัน 2.0 การสนับสนุนเพิ่มเติมสำหรับเบราว์เซอร์ Mozilla จะมองเห็นได้ผ่านสคริปต์ HTML และ JavaScript ที่เบราว์เซอร์สร้างขึ้นเท่านั้น
Lucene เป็น API การจัดทำดัชนีที่ใช้กันทั่วไปในโลก Java เมื่อใช้วิธีการที่มีให้ คุณสามารถสร้างดัชนีสำหรับเนื้อหาข้อความและจัดเตรียมการดึงข้อมูลได้ (อ้างอิง: NLucene และ Lucene .NET) NLucene เป็นพอร์ต .net แรกและเป็นเวอร์ชัน .net ที่ใช้หลักการตั้งชื่อ .net และการออกแบบไลบรารีคลาส อย่างไรก็ตาม เนื่องจากเหตุผลด้านพลังงาน ผู้นำโครงการ NLucene จึงเปิดตัวเวอร์ชัน 1.2beta เท่านั้น หลังจากที่โครงการ Lucene.NET เกิดขึ้น ก็ไม่มีแผนใหม่สำหรับ NLucene
เดิมที Lucene.NET อ้างว่าเป็นการปลูกถ่าย .net Lucene ที่ทันสมัย เพียงนำคำแนะนำของ .net มาใช้ในแง่ของการตั้งชื่อเท่านั้น เป้าหมายหลักมีแนวโน้มที่จะเข้ากันได้กับ Java Lucene: สิ่งหนึ่งคือทำให้รูปแบบดัชนีเข้ากันได้ พวกเขาสามารถทำงานร่วมกันได้ วัตถุประสงค์ประการหนึ่งคือการตั้งชื่อที่ใกล้เคียงกัน (มีความแตกต่างเพียงเล็กน้อย เช่น ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก เป็นต้น) และจุดประสงค์คือเพื่ออำนวยความสะดวกให้นักพัฒนาใช้โค้ดและข้อมูลที่เกี่ยวข้องกับ Java Lucene
ฉันไม่รู้ว่าเมื่อใดที่โครงการ Lucene.NET ยกเลิกแผนโอเพ่นซอร์สและหันมาทำธุรกิจ จริงๆ แล้วมันเป็นการลบไฟล์โอเพ่นซอร์สบน SourceForge ในเวลาเดียวกัน โครงการ dotLucene ก็ปรากฏบน SourceForge เพื่อประท้วง Lucene.NET นั้น dotLucene เกือบจะทำให้โค้ด Lucene.NET สมบูรณ์เป็นจุดเริ่มต้น ( https://sourceforge.net/forum/forum.php?thread_id=1153933&forum_id=408004 )
พูดตรงๆ Lucene.Net เป็นไลบรารีฟังก์ชันการดึงข้อมูล (Library) คุณสามารถใช้มันเพื่อเพิ่มฟังก์ชันการจัดทำดัชนีและการค้นหาให้กับแอปพลิเคชันของคุณ
แต่ผู้ใช้ Lucene.Net ไม่จำเป็นต้องมีความรู้เชิงลึกเกี่ยวกับการดึงข้อความแบบเต็ม เรียนรู้การใช้ไลบรารี่เท่านั้น หากคุณรู้วิธีเรียกใช้ฟังก์ชันต่างๆ ใน Library คุณจะสามารถใช้ฟังก์ชันการค้นหาข้อความแบบเต็มสำหรับแอปพลิเคชันของคุณได้
แต่อย่าคาดหวังว่า Lucene จะเป็นเครื่องมือค้นหาเช่น Google และ Baidu เครื่องมือ ไลบรารี คุณยังสามารถคิดว่ามันเป็น API ที่เรียบง่ายและใช้งานง่ายซึ่งรวมเอาฟังก์ชันการจัดทำดัชนีและการค้นหาเข้าด้วยกัน คุณสามารถทำสิ่งต่างๆ ที่เกี่ยวข้องกับการค้นหาได้มากมายด้วย API นี้ ซึ่งสะดวกและสามารถทำได้มาก ตอบสนองความต้องการของคุณ แอปพลิเคชันทำการค้นหาข้อความแบบเต็มอย่างง่าย ในฐานะนักพัฒนาแอปพลิเคชัน (ผู้พัฒนาเครื่องมือค้นหาที่ไม่ใช่มืออาชีพ) ฟังก์ชั่นของแอปพลิเคชันก็เพียงพอที่จะตอบสนองความต้องการของคุณ
2. Lucene.Net ทำอะไรได้บ้าง?
Lucene สามารถจัดทำดัชนีและค้นหาข้อมูลใดๆ ก็ได้ ไม่ว่าแหล่งข้อมูลจะมีรูปแบบใดก็ตาม ตราบใดที่สามารถแปลงเป็นข้อความได้ Lucene ก็สามารถวิเคราะห์และนำไปใช้ได้ other Lucene สามารถใช้ไฟล์รูปแบบใดก็ได้ตราบใดที่คุณสามารถแยกเนื้อหาข้อความออกมาได้ คุณสามารถใช้ Lucene เพื่อสร้างดัชนีและค้นหาไฟล์เหล่านั้น
ได้
มันสรุปง่ายๆ อยู่ที่ การสร้างดัชนี และการใช้ดัชนี การสร้างดัชนีคือการจัดเก็บหรือวิเคราะห์ข้อมูลของแหล่งข้อมูลที่จะค้นหาเป็นข้อมูลสำคัญของเรา และการทิ้งเครื่องหมายไว้สำหรับการค้นหาก็เหมือนกับการสร้างตารางของ เนื้อหาใน Word (ความเข้าใจส่วนบุคคล) โดยใช้ดัชนีคือการวิเคราะห์แหล่งข้อมูลตามข้อมูลดัชนีในระหว่างการค้นหาและดึงข้อมูลที่เราต้องการ
โปรดดูตัวอย่าง:
IntranetIndexer ระดับสาธารณะ
สำหรับการสร้างดัชนี
-
/////////ผู้เขียนดัชนี
ผู้เขียน IndexWriter ส่วนตัว
// ไดเรกทอรีรากของไฟล์ที่จะเขียนลงในดัชนี
สตริงส่วนตัว docRootDirectory;
//รูปแบบไฟล์ที่จะจับคู่
รูปแบบสตริงส่วนตัว [];
/**////// <summary>
/// เริ่มต้นตัวเขียนดัชนี Directory คือไดเร็กทอรีที่สร้างดัชนีไว้ จริง หมายความว่าหากไม่มีไฟล์ดัชนีอยู่ ไฟล์ดัชนีจะถูกสร้างขึ้นใหม่ หากมีไฟล์ดัชนีอยู่แล้ว เขียนทับ
/// </สรุป>
/// <param name="directory">ไดเร็กทอรีที่จะจัดทำดัชนีถูกส่งเข้ามา โปรดทราบว่าเป็นค่าสตริง หากไม่มีไดเร็กทอรีนั้น จะถูกสร้างขึ้นโดยอัตโนมัติ</param>
publicIntranetIndexer (ไดเร็กทอรีสตริง)
-
นักเขียน = IndexWriter ใหม่ (ไดเร็กทอรี, StandardAnalyzer ใหม่ (), จริง);
นักเขียน SetUseCompoundFile (จริง);
-
โมฆะสาธารณะ AddDirectory (ไดเร็กทอรี DirectoryInfo, รูปแบบสตริง [])
-
this.docRootDirectory = directory.FullName;
this.pattern = รูปแบบ;
addSubDirectory(ไดเร็กทอรี);
-
addSubDirectory เป็นโมฆะส่วนตัว (ไดเร็กทอรี DirectoryInfo)
-
สำหรับ(int i=0;i<รูปแบบ .Length ;i++)
-
foreach (FileInfo fi ในไดเร็กทอรี GetFiles (รูปแบบ [i]))
-
AddHtmlDocument(fi.FullName);
-
-
foreach (DirectoryInfo ใน directory.GetDirectories())
-
addSubDirectory(di);
-
-
โมฆะสาธารณะ AddHtmlDocument (เส้นทางสตริง)
-
สตริง exname=Path.GetExtension (เส้นทาง);
เอกสาร doc = เอกสารใหม่ ();
สตริง html;
if(exname.ToLower ()==".html" ||exname .ToLower ()==".htm"||exname .ToLower ()==".txt")
-
การใช้ (StreamReader sr=new StreamReader (เส้นทาง, System .Text .Encoding .Default ))
-
html = sr.ReadToEnd();
-
-
อื่น
-
ใช้ (StreamReader sr = StreamReader ใหม่ (เส้นทาง System.Text.Encoding.Unicode ))
-
html = sr.ReadToEnd();
-
}
intrelativePathStartsAt = this.docRootDirectory.EndsWith("\") ? this.docRootDirectory.Length : this.docRootDirectory.Length + 1;
สตริง RelativePath = path.Substring (relativePathStartsAt);
ชื่อสตริง = Path.GetFileName (เส้นทาง);
//ตรวจสอบว่าเป็นหน้าเว็บหรือไม่ ลบแท็ก ไม่เช่นนั้นอย่าใช้
if(exname.ToLower ()==".html" ||exname .ToLower ()==".htm")
-
doc.Add(Field.UnStored("ข้อความ", parseHtml(html)));
-
อื่น
-
doc.Add (ฟิลด์ .UnStored ("ข้อความ",html));
-
doc.Add(Field.Keyword("เส้นทาง", ญาติPath));
//doc.Add(Field.Text("title", getTitle(html)));
doc.Add (ฟิลด์ .Text ("title",title));
นักเขียน AddDocument (doc);
-
/***////// <สรุป>
/// ลบแท็กออกจากหน้าเว็บ
/// </สรุป>
/// <param name="html">เว็บเพจ</param>
/// <returns>ส่งคืนข้อความหน้าเว็บที่ถูกลบ</returns>
สตริงส่วนตัว parseHtml (สตริง html)
-
สตริงชั่วคราว = Regex.Replace(html, "<[^>]*>", "");
กลับtemp.Replace(" ", " ");
-
/***////// <สรุป>
/// รับชื่อเพจ
/// </สรุป>
/// <ชื่อพารามิเตอร์="html"></param>
/// <ส่งคืน></ส่งคืน>
สตริงส่วนตัว getTitle (สตริง html)
-
จับคู่ m = Regex.Match(html, "<title>(.*)</title>");
ถ้า (m.Groups.Count == 2)
กลับ m.Groups[1].Value;
กลับ "ไม่ทราบชื่อเอกสาร";
-
/***////// <สรุป>
/// ปรับดัชนีให้เหมาะสมและปิดตัวเขียน
/// </สรุป>
โมฆะสาธารณะ ปิด()
-
นักเขียนเพิ่มประสิทธิภาพ ();
นักเขียน.ปิด();
-
}
ขั้นแรกให้สร้างออบเจ็กต์ Document จากนั้นเพิ่มฟิลด์คุณลักษณะบางอย่างให้กับออบเจ็กต์ Document คุณสามารถคิดว่าออบเจ็กต์ Document เป็นไฟล์เสมือน ซึ่งข้อมูลจะได้รับในอนาคต ฟิลด์จะถือเป็นข้อมูลเมตาที่อธิบายไฟล์เสมือนนี้ ในบรรดาฟิลด์เหล่านั้นมีสี่ประเภท:
ข้อมูลงานคีย์ประเภทนี้จะไม่ได้รับการวิเคราะห์ แต่จะถูกจัดทำดัชนีและบันทึกในดัชนี
ไม่ได้จัดทำดัชนี
ข้อมูลประเภทนี้จะไม่ได้รับการวิเคราะห์หรือจัดทำดัชนี แต่จะถูกเก็บไว้ในดัชนี
ไม่ได้จัดเก็บ
ตรงกันข้ามกับ UnIndexed คือมีการวิเคราะห์และจัดทำดัชนี แต่ไม่ได้บันทึก
ข้อความ
คล้ายกับ UnStored หากประเภทค่าเป็นสตริง ระบบจะบันทึก หากประเภทค่าเป็น Reader ระบบจะไม่บันทึกเช่นเดียวกับ UnStored
สุดท้าย แต่ละเอกสารจะถูกเพิ่มลงในดัชนี
ต่อไปนี้เป็นการค้นหาดัชนี
//สร้างตัวสร้างดัชนี
ผู้ค้นหา IndexSearcher = IndexSearcher ใหม่ (indexDirectory);
// แยกช่องข้อความของดัชนีเพื่อค้นหา
แบบสอบถามแบบสอบถาม = QueryParser.Parse (this.Q, "ข้อความ", StandardAnalyzer ใหม่ ());
//ใส่ผลการค้นหาเป็น Hit
ฮิต ฮิต = searcher.Search(query);
//สถิติจำนวนบันทึกทั้งหมดที่ค้นหา
this.total = hits.Length();
//ไฮไลท์
QueryHighlightExtractor highlighter = ใหม่ QueryHighlightExtractor(แบบสอบถาม, StandardAnalyzer ใหม่ (), "<font color=red>", "</font>");
ขั้นตอนแรกคือการใช้ IndexSearcher เพื่อเปิดไฟล์ดัชนีสำหรับการค้นหาครั้งต่อไป และพารามิเตอร์คือเส้นทางของไฟล์ดัชนี
ขั้นตอนที่สองคือการใช้ QueryParser เพื่อแปลงคำสั่งแบบสอบถามที่สามารถอ่านได้มากขึ้น (เช่น คำค้นหา lucene และคำสั่งบางอย่าง วิธีการขั้นสูง lucene AND.net) ลงในวัตถุแบบสอบถามที่ใช้ภายในโดย Lucene
ขั้นตอนที่สามดำเนินการค้นหาและส่งกลับผลลัพธ์ไปยังคอลเลกชัน Hits ควรสังเกตว่า Lucene ไม่ได้ใส่ผลลัพธ์ทั้งหมดลงใน Hit พร้อมกัน ทีละส่วน สำหรับการพิจารณาพื้นที่
ผลลัพธ์การค้นหาจะถูกประมวลผลและแสดงบนเพจ:
for (int i = startAt; i < resultsCount; i++)
-
เอกสาร doc = hits.Doc(i);
string path = doc.Get("path");
string location =Server.MapPath("documents")+" \"+path ;
สตริง exname=Path.GetExtension (เส้นทาง);
สตริงข้อความธรรมดา;
string str=doc.Get ("ชื่อ");
if(exname==".html" || exname ==".htm" || exname ==".txt")
-
ใช้ (StreamReader sr = StreamReader ใหม่ (ตำแหน่ง System.Text.Encoding.Default))
-
plainText = parseHtml(sr.ReadToEnd());
-
-
อื่น
-
ใช้ (StreamReader sr = StreamReader ใหม่ (ตำแหน่ง System.Text.Encoding.Unicode ))
-
ข้อความธรรมดา = sr.ReadToEnd();
-
-
//DataTable เพิ่มแถว
แถว DataRow = this.Results.NewRow();
แถว["title"] = doc.Get("title");
string IP=Request.Url.Host;//รับ IP ของเซิร์ฟเวอร์
//Request.Url.พอร์ต;
แถว["เส้นทาง"]=@" http://"+IP+"/WebUI/Search/documents/"+path ;
row["sample"] = highlighter.GetBestFragments(ข้อความธรรมดา, 80, 2, "");
this.Results.Rows.Add(แถว);
-
searcher.Close();//ปิดผู้ค้นหา หากคุณต้องการทำความเข้าใจ Lucene.Net ขั้นสูง ครอบคลุม และเจาะลึกยิ่งขึ้น โปรดดูที่เว็บไซต์:
http: //blog.tianya.cn/blogger/view_blog.asp?BlogName=aftaft