Lucene은 .NET에서 전체 텍스트 검색을 지원하는 효율적이고 강력한 검색 엔진입니다. 텍스트 검색을 쉽게 만들고 빠르고 사용자 친화적인 텍스트 검색 기술을 위해 풍부한 API 세트를 제공합니다.
또한 Lucene이 제공하지 않는 한 가지가 있는데 바로 확장성입니다. Lucene 응용 프로그램은 일반적으로 파일에 데이터를 쓰고 디스크에 저장하므로 상당한 메모리 할당이 발생합니다. NCache 를 제공합니다 분산 루신 Lucene 애플리케이션을 확장 가능하고 분산되도록 만드는 기능입니다. 또한 단일 장애 지점 문제에 대해 선형적으로 확장 가능하고 분산된 대안을 제공합니다.
NCache 세부 정보 분산 Lucene의 작업 분산 Lucene 문서
Distributed Lucene에 대한 자세한 내용은 작동 중이며 왜 이 옵션을 선택해야 하는지는 여기를 참조하십시오. 분산 Lucene: 확장성을 위해 .NET에서 전체 텍스트 검색. Distributed Lucene에 대해 자세히 알아보기 전에 기본 워크플로를 보여주는 Distributed Lucene 솔루션을 살펴보겠습니다.
아래 코드 샘플은 주로 다음 세 단계를 수행하는 분산 Lucene을 보여줍니다.
- 초기화 NCache 예배 규칙서.
- 검색을 수행하기 위해 문서를 인덱싱합니다.
- 인덱싱된 문서에서 검색을 수행합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
{ // Specify the cache name that is used for Lucene string cache = "LuceneCache"; // Specify the index name to create the indexes string indexName = "ProductIndex"; // Create a directory and open it on the cache and the index path Directory directory = NCacheDirectory.Open(cache, indexName); // Specify the analyzer used to analyze data Analyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48); // Create an indexWriterConfig which holds all the configurations to create an instance of the writer IndexWriterConfig config = new IndexWriterConfig(LuceneVersion.LUCENE_48, analyzer); // Create the indexWriter with the analyzer and the configuration IndexWriter indexWriter = new IndexWriter(directory, config); // Add the products information that is to be indexed Product[] products = FetchProductsFromDB(); foreach (var prod in products) { // Create a document and add fields to it Document doc = new Document(); doc.Add(new TextField("id", prod.ProductID(), Field.Store.YES)); doc.Add(new TextField("name", prod.ProductName, Field.Store.NO)); doc.Add(new TextField("category", prod.Category, Field.Store.YES)); doc.Add(new TextField("description", prod.Description, Field.Store.YES)); // Writer is created previously indexWriter.AddDocument(doc); // Call ‘Commit’ to save the changes indexWriter.Commit(); } // Open a new reader instance IndexReader reader = indexWriter.GetReader(true); // A searcher is opened to perform searching IndexSearcher indexSearcher = new IndexSearcher(reader); // Specify the searchTerm and the fieldName string searchTerm = "Beverages"; string fieldName = "Category"; LuceneVersion version = LuceneVersion.LUCENE_48; // Create a query parser and parse the query with the parser // Analyzer is whitespace analyzer as specified beforehand QueryParser parser = new QueryParser(version, fieldName, analyzer); Query query = parser.Parse(searchTerm); // Returns the top 10 hits from the result set ScoreDoc[] docsFound = indexSearcher.Search(query, 10).ScoreDocs; // Closes all the files associated with this index reader.Dispose(); } catch(Exception ex) { // Handle Lucene exceptions } |
이 블로그에서는 전체 텍스트 검색을 위한 분산 Lucene의 자세한 단계와 작업에 중점을 두고 있습니다.
NCache 세부 정보 분산 Lucene의 작업 Lucene 구성 요소 및 개요
분산 Lucene으로 마이그레이션하는 방법은 무엇입니까?
분산 Lucene은 Lucene과 동일하게 작동합니다. 분산형 Lucene을 사용할 때의 한 가지 큰 편안함은 Lucene과 동일한 API를 제공한다는 것입니다. Lucene 사용자는 단일 라이너 코드 변경의 추가 기능으로 원하는 확장성을 얻을 수 있습니다. 사용하기만 하면 된다 NCache 디렉토리와 응용 프로그램을 사용할 수 있습니다. 설명서에 나열된 분산 Lucene의 동작 및 API 변경 사항은 거의 없습니다. 여기에서 지금 확인해 보세요..
기술적인 측면에서 이러한 단계를 자세히 살펴보겠습니다.
1단계: 연결 NCache 명부 담당
소개를 시작하겠습니다. NCache Lucene을 사용하여 .NET 애플리케이션에서 기본 단계는 라이브러리의 Lucene.NET Nuget 패키지를 다음으로 바꾸는 것입니다. NCache님의 Nuget 패키지입니다. NCache 디렉토리는 이름에서 알 수 있듯이 인덱스를 확장 가능하게 만들기 위해 인덱스를 저장하는 기본 클래스입니다. Lucene.NET에는 이 목적을 위한 여러 디렉토리 구현이 있지만 가장 일반적으로 사용되는 것은 FSDirectory입니다. 따라서 첫 번째 단계는 다음과 연결을 설정하는 것입니다. NCache 예배 규칙서.
아래는 라는 캐시에 연결하는 코드입니다. "루신캐시" 이 디렉토리가 이미 존재하는 경우 모든 기존 서버에서 제공된 디렉토리를 엽니다. 그렇지 않으면 제공된 이름으로 새 디렉토리를 생성합니다.
1 |
var indexDirectory = NCacheDirectory.Open("luceneCache", new DirectoryInfo("lucene-index-path")); |
이것으로, NCache Distributed Lucene을 사용하려면 또 다른 작은 단계가 필요합니다. 관리 도구를 사용하여 분산 Lucene을 사용하는 캐시에 대해 Lucene 인덱스를 활성화합니다. 참조하십시오 이 챕터 NCache 수행 지침에 대한 문서입니다.
루씬 설정 엔터프라이즈 검색을 위한 분산 Lucene 분산 Lucene 문서
2단계: 분산 Lucene 인덱스 생성 NCache
이제 그 NCache Lucene 응용 프로그램에 통합되고 데이터 쓰기 단계가 시작됩니다. 앞서 논의한 바와 같이 Lucene은 인덱스 형식으로 레코드를 인덱싱합니다. 이러한 인덱스는 선형 확장성을 제공하는 노드에서 별도로 유지됩니다. 캐시 노드 간의 문서 배포는 자동으로 처리됩니다. NCache.
문서는 키-값 쌍인 필드로 구성됩니다. 각 필드에는 사용자가 검색할 수 있는 텍스트가 포함되어 있습니다. 필드 생성자의 다른 부분에는 개별 필드를 처리하기 위한 지침이 포함되어 있습니다.
이러한 문서는 NCache Lucene 반전 인덱스 형식의 디렉터리입니다. Lucene은 텍스트를 토큰 형태로 분해합니다. 인덱싱을 위해 텍스트를 분해하는 이 프로세스는 분석기를 사용하여 수행됩니다. 다음과 같은 여러 유형의 분석기가 있습니다. 공백 분석기 or 표준 분석기. 이러한 데이터 토큰화는 분석기의 주요 목적이 노이즈 단어를 제거하고 검색이 수행되는 나머지 데이터를 인덱싱하는 것이므로 더 빠른 데이터 검색에 도움이 됩니다. 분석기에 대한 완전한 지식은 이 페이지를 참조하십시오.
문서는 IndexWriter를 사용하여 디렉토리에서 인덱싱됩니다. IndexWriter는 캐시에서 모든 쓰기 작업을 수행합니다. 보다 정확하게는 FieldStore와 같은 다른 필드 속성을 추가하여 검색을 효율적으로 만들 수 있습니다. 아래 코드는 캐시에 문서를 (대량으로) 작성하고 결과적으로 모든 캐시 서버에서 인덱스를 생성하는 방법을 자세히 설명합니다. 모든 쓰기 작업 후에 반드시 Commit을 호출하십시오. 그렇지 않으면 검색을 수행하기 위한 작업이 기록되지 않습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public int AddDocuments () { var analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48); var writerConfig = new IndexWriterConfig (LuceneVersion.LUCENE_48, analyzer); var indexWriter = new IndexWriter (indexDirectory, writerConfig); var docCount = 0; // Fetching repository info from data source using (var enumerator = dataProvider.GetProductFTSEnumerator ()) { while (enumerator.MoveNext ()) { docs.Add (enumerator.Current.GetLuceneDocument ()); docCount++; // Perform commit after the chunk of code if (docs.Count == BULK_SIZE) { indexWriter.AddDocuments (docs); //Flush and make it ready for search indexWriter.Commit (); docs.Clear (); //Remove the added documents } } } // Return the count of added documents return docCount; } |
NCache 세부 정보 분산 Lucene의 작업 분산 Lucene에 대한 지리 공간 인덱스
3단계: 확장성 있는 데이터 검색 전체 텍스트
분산 Lucene을 사용하여 캐시에서 데이터를 검색하는 실제 작업은 이 단계에서 나옵니다. 데이터 인덱싱과 유사하게 캐시의 모든 노드에서 읽기도 수행되고 검색 결과는 결국 병합됩니다. 이렇게 하면 읽기 확장성도 증가하고 검색 속도가 빨라집니다.
Lucene의 IndexWriter와 유사하게 인덱스 검색자 검색을 기반으로 데이터 읽기 작업을 수행하기 위해 모든 무거운 작업을 수행합니다. IndexSearcher는 분석기를 통과하며 이전에 데이터를 작성하는 데 사용된 것과 동일한 분석기를 검색에 사용하는 것이 좋습니다. 그렇지 않으면 결과가 일치하지 않습니다.
다음으로 검색을 수행하기 위해 Lucene이 사용하는 것은 쿼리. Lucene 특정 구문과 함께 필요에 따라 Lucene에는 다양한 기본 제공 쿼리 클래스가 있습니다. 이러한 쿼리는 검색을 매우 효율적으로 만듭니다. 예를 들어 와일드카드를 사용하여 검색을 수행하고 그에 따라 검색 결과를 렌더링하는 와일드카드 쿼리가 있습니다. 일부 다른 쿼리 유형은 TermQuery, BooleanQuery 및 SpanQuery입니다.
검색 결과는 수행된 검색 결과로 반환된 문서 목록인 적중 형식으로 반환됩니다. 그런 다음 이러한 조회를 반복하여 쿼리와 일치하는 실제 문서를 얻을 수 있습니다.
아래에 제공된 코드는 Lucene 색인에서 수행되는 검색을 목격하는 데 도움이 될 것입니다. IndexSearcher는 결과를 가져오기 위해 IndexReader를 사용합니다. 쿼리는 인덱싱된 데이터에 대한 실제 검색을 수행하는 데 사용됩니다. QueryParser는 분석기에 따라 사용자가 제공한 텍스트 쿼리를 구문 분석하고 검색어와 결과는 TopDocs 형식으로 반환됩니다.
아래 주어진 예에서 QueryWrapperFilter는 제품 카테고리에 적용되고 검색 결과는 관련성을 기준으로 정렬됩니다. 쿼리는 최적의 결과를 제공하기 위해 모든 용어에 퍼지를 적용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public Tuple<long, List<RepositoryInfo>> Search (string searchTerm, int top = 100, string category = null) { long totalHints = 0; var repoList = new List<ProductFTS> (); // Now create the IndexSearcher instance to search the data // directoryReader is the IndexReader instance which uses the IndexWriter var searcher = new IndexSearcher (directoryReader); try { TopDocs topDocs = null; var queryParser = new MultiFieldQueryParser (Version, Fields, analyzer); var query = new BooleanQuery (); // Split the search term into multiple search words to make fuzzy query string[] terms = searchTerm.Split (new [] { " " }, StringSplitOptions.RemoveEmptyEntries); foreach (string term in terms) query.Add (queryParser.Parse (term.Replace ("~", "") + "~"), Occur.MUST); // remove the duplicate ~, if already exits if (!string.IsNullOrEmpty (category)) { var filter = new QueryWrapperFilter (new TermQuery (new Term (CATEGORY_FIELD, category))); // Performs the search based on the filter applied topDocs = searcher.Search (query, filter, top, Sort.RELEVANCE); } else { topDocs = searcher.Search (query, top, sort : Sort.RELEVANCE); } totalHits = topDocs.TotalHits; repoList = GetSearchedDocs (searcher, topDocs); } return new Tuple<long, List<ProductFTS>> (totalHits, repoList); } |
그런 다음 비즈니스 로직을 구현하여 적중에서 검색 결과를 반복할 수 있습니다.
결론
Lucene은 데이터에 대한 전체 텍스트 검색을 수행하기 위한 매우 효율적인 검색 엔진이지만 확장성이 부족합니다. NCache Lucene과 함께 사용하여 아주 적은 노력으로 확장할 수 있습니다. 확장 가능한 분산형 Lucene은 애플리케이션을 더 빠르게 만들 뿐만 아니라 단일 실패 지점의 주요 문제를 처리하는 데 도움이 됩니다. NCache 한 줄의 코드 변경으로 .NET 응용 프로그램에 쉽게 연결할 수 있으므로 확장 가능한 Lucene 응용 프로그램에 가장 적합한 옵션이라고 생각하십시오.