O Lucene é um mecanismo de pesquisa eficiente e poderoso que oferece suporte à pesquisa de texto completo em .NET. Ele facilita a pesquisa de texto e fornece um rico conjunto de APIs, para técnicas de pesquisa de texto rápidas e fáceis de usar.
Além disso, há uma coisa que o Lucene não oferece: escalabilidade. Os aplicativos Lucene geralmente gravam dados em um arquivo e os armazenam no disco, resultando em uma alocação de memória significativa. NCache fornece uma Lucene distribuído recurso que torna seus aplicativos Lucene escaláveis e distribuídos. Ele também fornece uma alternativa linearmente escalável e distribuída para o problema de um único ponto de falha.
NCache Adicionar ao carrinho Trabalho de Lucene Distribuído Documentos distribuídos do Lucene
Para obter mais informações sobre o Lucene distribuído, está funcionando e por que deve ser sua opção preferida, dê uma olhada nisso Lucene distribuído: pesquisa de texto completo no .NET para escalabilidade. Antes de entrar nos detalhes do Distributed Lucene, vamos examinar uma solução Distributed Lucene demonstrando o fluxo de trabalho básico.
O exemplo de código abaixo mostra um Lucene distribuído que executa principalmente estas três etapas:
- Inicialize o NCache Diretório.
- Indexe os documentos para realizar uma pesquisa sobre eles.
- Faça uma pesquisa nos documentos indexados.
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 } |
Neste blog, estamos nos concentrando nas etapas detalhadas e no trabalho do Lucene distribuído para pesquisa de texto completo.
NCache Adicionar ao carrinho Trabalho de Lucene Distribuído Componentes e visão geral do Lucene
Como migrar para o Lucene distribuído?
O Lucene distribuído funciona exatamente como o Lucene. Um grande conforto de usar o Lucene distribuído é que ele oferece a mesma API que o Lucene. Como usuário do Lucene, você obtém a escalabilidade que deseja com um complemento de uma única alteração de código de linha. Você só tem que usar NCache Directory e seu aplicativo estão prontos. Existem muito poucas mudanças comportamentais e de API no Lucene distribuído que estão listadas na documentação SUA PARTICIPAÇÃO FAZ A DIFERENÇA.
Vamos dar uma olhada nessas etapas de um aspecto técnico.
Etapa 1: Conectando-se a NCache Diretório
Comecemos por apresentar NCache em seu aplicativo .NET usando o Lucene. A etapa principal é substituir o pacote Lucene.NET Nuget da sua biblioteca por NCache's pacote Nuget. NCache Directory, como o nome sugere, é uma classe base para armazenar os índices para torná-los escaláveis. Lucene.NET tem várias implementações de diretório para essa finalidade, mas a mais comumente usada é FSDirectory. Assim, o primeiro passo é estabelecer uma conexão com o NCache Diretório.
Abaixo está o código que o conecta a um cache chamado “luceneCache” e abre o diretório fornecido em todos os servidores existentes, desde que esse diretório já exista. Caso contrário, ele apenas cria um novo diretório com o nome fornecido.
1 |
var indexDirectory = NCacheDirectory.Open("luceneCache", new DirectoryInfo("lucene-index-path")); |
Com isso, NCache requer outro pequeno passo para usar o Distributed Lucene. Usando qualquer ferramenta de gerenciamento, ative o índice Lucene para o cache usando Lucene distribuído. Por favor, consulte isto capítulo em NCache Documentação para orientações sobre como fazê-lo.
Configurar Lucene Lucene distribuído para pesquisa corporativa Documentos distribuídos do Lucene
Etapa 2: Criando Índices Lucene Distribuídos com NCache
Agora que NCache é incorporado ao seu aplicativo Lucene, vem a fase de gravação de dados. Conforme discutido anteriormente, o Lucene indexa seus registros na forma de índices. Esses índices são mantidos nos nós separadamente, fornecendo escalabilidade linear. A distribuição de documentos entre os nós de cache é tratada automaticamente por NCache.
Os documentos são formados a partir de campos que são pares de valores-chave. Cada campo contém o texto que deve ser pesquisável por você. As outras partes do construtor do campo contêm instruções para lidar com um campo individual.
Esses documentos são armazenados no NCache Diretório na forma de índices invertidos Lucene. Lucene divide o texto na forma de tokens. Esse processo de quebra de textos para indexação é feito por meio de analisadores. Existem vários tipos de analisadores, como analisadores de espaço em branco or analisadores padrão. Essa tokenização de dados ajuda na pesquisa de dados mais rápida, pois o principal objetivo dos analisadores é remover as palavras de ruído e indexar o restante dos dados nos quais a pesquisa é realizada. Para um conhecimento completo dos analisadores, consulte esta página.
Os documentos são indexados no diretório usando IndexWriter. IndexWriter é responsável por executar todas as operações de gravação no cache. Mais precisamente, você pode adicionar outras propriedades de campo para tornar a pesquisa eficiente, como FieldStore. O código abaixo explica detalhadamente a gravação de documentos (em massa) no cache e, como resultado, a criação de índices em todos os servidores de cache. Certifique-se de chamar Commit após cada operação de gravação, caso contrário, a operação não será gravada para realizar a pesquisa.
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 Adicionar ao carrinho Trabalho de Lucene Distribuído Índices Geoespaciais para Lucene Distribuído
Etapa 3: texto completo pesquisando os dados com escalabilidade
A tarefa real de pesquisar dados no cache usando o Lucene distribuído vem nesta etapa. Semelhante à indexação de dados, as leituras também são realizadas em todos os nós do cache e os resultados da pesquisa são mesclados eventualmente. Isso também aumenta a escalabilidade de leitura e torna a pesquisa mais rápida.
Semelhante ao IndexWriter no Lucene, há uma Pesquisador de índice que faz todo o trabalho pesado para executar as operações de leitura de dados com base na pesquisa. IndexSearcher passa um analisador, e é altamente recomendável usar o mesmo analisador para pesquisa, que foi usado anteriormente para gravar os dados, caso contrário, os resultados serão inconsistentes.
A próxima coisa que o Lucene usa para realizar pesquisas é o consultas. Há uma ampla variedade de classes de consulta integradas no Lucene de acordo com suas necessidades, juntamente com uma sintaxe específica do Lucene. Essas consultas tornam sua pesquisa bastante eficiente, por exemplo, há uma consulta curinga que executa uma pesquisa usando curingas e renderiza os resultados da pesquisa de acordo. Alguns outros tipos de consulta são TermQuery, BooleanQuery e SpanQuery.
Os resultados da pesquisa são retornados na forma de hits, que é uma lista de documentos retornados como resultado da pesquisa realizada. Esses hits podem ser iterados para obter o documento real que corresponde à consulta.
O código fornecido abaixo ajudará você a testemunhar a pesquisa realizada nos índices do Lucene. IndexSearcher usa o IndexReader para buscar os resultados. Uma consulta é usada para realizar a pesquisa real nos dados indexados. Um QueryParser analisa a consulta textual fornecida pelo usuário de acordo com o analisador e os termos de pesquisa e os resultados são retornados na forma de TopDocs.
No exemplo abaixo, um QueryWrapperFilter é aplicado na categoria Produtos e os resultados da pesquisa são classificados por relevância. A consulta aplica imprecisão a todos os termos para fornecer resultados ideais.
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); } |
Você pode então implementar sua lógica de negócios para iterar os resultados da pesquisa dos hits.
Conclusão
O Lucene é um mecanismo de pesquisa altamente eficiente para realizar pesquisas de texto completo em seus dados, mas carece de escalabilidade. NCache pode ser usado com o Lucene para torná-lo escalável com muito pouco esforço. O Lucene distribuído escalável torna seu aplicativo não apenas mais rápido, mas também o ajuda a lidar com o grande revés do ponto único de falha. NCache pode ser facilmente conectado ao seu aplicativo .NET com uma alteração de código de linha única, portanto, considere-a a melhor opção possível para seu aplicativo Lucene escalável.
NCache Adicionar ao carrinho Baixar NCache Comparação de edições