/// <summary> /// Converts a <see cref="Document" /> object to a <see cref="LuceneDocument" /> object. /// </summary> /// <param name="document">The Document object</param> /// <param name="schema">The schema.</param> /// <param name="facetBuilder">The Lucene facet builder.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidOperationException">Cannot index a Document that does not have an _id.</exception> /// <exception cref="SchemaException">The fieldName '{fieldName}'</exception> /// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.InvalidOperationException">Cannot index a Document that does not have an _id.</exception> public static LuceneDocument ToLuceneDocument(this Document document, Schema schema = null, LuceneFacetBuilder facetBuilder = null) { if (document == null) throw new ArgumentNullException(nameof(document)); if (schema == null) schema = Schema.CreateDefault(); var documentDictionary = document.AsDictionary(); if (!documentDictionary.ContainsKey(Schema.StandardField.ID)) throw new InvalidOperationException("Cannot index a Document that does not have an _id."); var luceneDocument = new LuceneDocument(); // Make sure the _id field is the first field added to the Lucene document var keys = documentDictionary.Keys.Except(new[] { Schema.StandardField.ID }).ToList(); keys.Insert(0, Schema.StandardField.ID); foreach (var fieldName in keys) { // Validate fieldName - must not contain space or Lucene QueryParser illegal characters. if (_queryParserIllegalCharsRegex.IsMatch(fieldName)) throw new SchemaException($"The fieldName '{fieldName}' contains illegal characters."); Schema.Field schemaField = null; if (!schema.Fields.TryGetValue(fieldName, out schemaField)) { schemaField = new Schema.Field { Name = fieldName }; schema.Fields.TryAdd(fieldName, schemaField); } var fieldValue = documentDictionary[fieldName]; var luceneFields = fieldValue.ToLuceneFields(schemaField); foreach (var luceneField in luceneFields) luceneDocument.Add(luceneField); } // The full-text field is always auto-generated and added to the Lucene document. var fullText = document.ToLuceneFullTextString(); luceneDocument.Add(new TextField(Schema.StandardField.FULL_TEXT, fullText, FieldStore.NO)); // Check if the document has the special _categories field, // which means that we need to create facets for it. if (document.HasCategories() && facetBuilder != null) luceneDocument = facetBuilder.RebuildDocumentWithFacets(luceneDocument, document, schema); return luceneDocument; }
/// <summary> /// Initializes a new instance of the <see cref="LuceneIndex" /> class. /// </summary> /// <param name="indexPath">The path to the directory that will contain the Lucene index files.</param> /// <param name="schema">The schema.</param> /// <exception cref="System.ArgumentNullException"></exception> public LuceneIndex(string indexPath, Schema schema) { if (String.IsNullOrWhiteSpace(indexPath)) throw new ArgumentNullException(nameof(indexPath)); if (schema == null) throw new ArgumentNullException(nameof(schema)); IndexPath = indexPath; Schema = schema; if (System.IO.Directory.Exists(IndexPath)) { if (Schema.IsDefault()) throw new InvalidOperationException($"There is an existing index on '{IndexPath}'."); } else { System.IO.Directory.CreateDirectory(IndexPath); } _indexDirectory = new MMapDirectory(Paths.get(IndexPath)); var taxonomyIndexPath = System.IO.Path.Combine(IndexPath, "taxonomy"); if (!System.IO.Directory.Exists(taxonomyIndexPath)) System.IO.Directory.CreateDirectory(taxonomyIndexPath); _taxonomyDirectory = new MMapDirectory(Paths.get(taxonomyIndexPath)); _compositeAnalyzer = new CompositeAnalyzer(Schema); _ramBufferSizeMB = Double.Parse(ConfigurationManager.AppSettings["IndexWriter.RAMBufferSizeMB"] ?? "128"); var config = new IndexWriterConfig(_compositeAnalyzer) .SetOpenMode(IndexWriterConfigOpenMode.CREATE_OR_APPEND) .SetRAMBufferSizeMB(_ramBufferSizeMB) .SetCommitOnClose(true); _indexWriter = new IndexWriter(_indexDirectory, config); _taxonomyWriter = new DirectoryTaxonomyWriter(_taxonomyDirectory, IndexWriterConfigOpenMode.CREATE_OR_APPEND); _searcherTaxonomyManager = new SearcherTaxonomyManager(_indexWriter, true, null, _taxonomyWriter); _facetBuilder = new LuceneFacetBuilder(_taxonomyWriter); _refreshIntervalSeconds = Double.Parse(ConfigurationManager.AppSettings["IndexSearcher.RefreshIntervalSeconds"] ?? "0.5"); _commitIntervalSeconds = Double.Parse(ConfigurationManager.AppSettings["IndexWriter.CommitIntervalSeconds"] ?? "60"); _writeAllowedFlag = new ManualResetEventSlim(true); _refreshTimer = new Timer(o => Refresh(), null, TimeSpan.FromSeconds(_refreshIntervalSeconds), TimeSpan.FromSeconds(_refreshIntervalSeconds)); _commitTimer = new Timer(o => Commit(), null, TimeSpan.FromSeconds(_commitIntervalSeconds), TimeSpan.FromSeconds(_commitIntervalSeconds)); }