FullTextSearchDemo is a project that provides search engine services for full-text search in documents. It utilizes Lucene.NET for indexing and searching documents efficiently.
TBD
Start by configuring the model you want to search by implementing the IDocument interface in your class.
public class Product : IDocument
{
public string UniqueKey => Id.ToString();
public int Id { get; set; }
...
}
Please note that the UniqueKey is used for updating and deleting documents. It is crucial to ensure that each document has a unique UniqueKey, as shared UniqueKey values among documents can lead to unintended consequences during update and delete operations.
Create an class implemeting the IIndexConfiguration<T>
interface, where T
is the type of documents you want to search.
public class ProductConfiguration : IIndexConfiguration<Product>
{
public string IndexName => "product-index";
}
The index name is the folder where Lucene.NET will store the indexed data and related files.
Register the search engine services using the provided extension method on IServiceCollection.
...
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddSearchEngineServices(new ProductConfiguration());
var app = builder.Build();
...
To add a single document to the search engine, use the Add method.
var newProduct = new Product
{
Id = 1,
Name = "Sample Product",
Description = "This is a sample product description."
};
_searchEngine.Add(newProduct);
The AddRange method is designed to add a collection of documents:
var products = new List<Product>();
// Add items to the list
_searchEngine.AddRange(products);
To update an existing document in the search engine, use the Update method providing the updated document.
var updatedProduct = new Product
{
Id = 1,
Name = "Updated Product",
Description = "This is an updated product description."
};
_searchEngine.Update(updatedProduct);
To remove a single document from the search engine, use the Remove method providing the document.
var product = new Product
{
Id = 1,
Name = "Updated Product",
};
_searchEngine.Remove(product);
If you desire to remove all documents from the index you can use the Clear method.
_searchEngine.RemoveAll();
Since the IndexWriter is kept as Singleton everytime that a document is added it is kept in memory. To free this memory allocations you can use the method:
_searchEngine.DisposeResources();
It is still safe to use the
You can perform searches based on specific fields within your documents using the FieldSpecificSearchQuery. Here's an example of how to search for products by their name and description.
var searchTerm = new Dictionary<string, string?>();
searchTerm.Add(nameof(Product.Name), "MyProduct");
searchTerm.Add(nameof(Product.Description), "Its description");
var searchQuery = new FieldSpecificSearchQuery
{
SearchTerms = searchTerm,
PageNumber = 1,
PageSize = 10,
Type = SearchType.ExactMatch
};
var result = _searchEngine.Search(searchQuery);
To perform a full-text search across all fields of your documents, use the AllFieldsSearchQuery. This allows you to find documents that match a search term regardless of the field.
var fullTextQuery = new AllFieldsSearchQuery
{
SearchTerm = "Sample Product",
PageNumber = 1,
PageSize = 10,
Type = SearchType.FuzzyMatch
};
var fullTextResult = searchEngine.Search(fullTextQuery);
To enable a property to act as facet, it is necessary to annotate it with the FacetProperty
attribute.
public class Movie : IDocument
{
...
[FacetProperty]
public string TitleType { get; set; }
...
}
When a property is of type string[], in addition to adding the FacetProperty attribute, it is necessary to configure the field as a multivalued field.
public class Movie : IDocument
{
...
[FacetProperty]
public string[] Genres { get; set; }
...
}
The MoviesConfiguration shows how to configure the multivalued field correctly:
public class MoviesConfiguration : IIndexConfiguration<Movie>
{
public string IndexName => "movies-index";
public FacetConfiguration<Movie>? FacetConfiguration => new()
{
MultiValuedFields = new[] { nameof(Movie.Genres) }
};
}
If the facet feature is not necessary, you set the FacetConfiguration
to null.
public class PostTestConfiguration : IIndexConfiguration<Post>
{
public string IndexName => "post-test-index";
public FacetConfiguration<Post>? FacetConfiguration => null;
}
All public queries expose the Facets dictionary, where the key represents the property name and the value represents the facet search value.
var facets = new Dictionary<string, IEnumerable<string?>?>();
facets.Add(nameof(Movie.Genres), new string[]{"Comedy", "Drama", "Action"});
_searchEngine.Search(new AllFieldsSearchQuery { Facets = facets });
Copyright 2023 José Rojas Jimenez
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of th*.doce License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.