Created
September 26, 2019 13:43
-
-
Save Shazwazza/3d32f4f37d9adadfe56400d0c24db6bd to your computer and use it in GitHub Desktop.
Example of creating a custom lucene index in Umbraco 8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Custom service to work with products | |
/// </summary> | |
public interface IProductService | |
{ | |
IEnumerable<Product> GetAll(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Product model | |
/// </summary> | |
public class Product | |
{ | |
public System.Guid Id { get; set; } | |
public string Name { get; set; } | |
public double Price { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Custom implementation of LuceneIndex in order to implement <see cref="IIndexDiagnostics"/> | |
/// </summary> | |
public class ProductIndex : LuceneIndex, IIndexDiagnostics | |
{ | |
//NOTE: None of this will be necessary in 8.2 if you just want to use the underlying LuceneIndex object | |
// see: https://github.com/umbraco/Umbraco-CMS/pull/6447 | |
public ProductIndex(string name, Directory luceneDirectory, FieldDefinitionCollection fieldDefinitions, Analyzer analyzer, IProfilingLogger profilingLogger) | |
: base(name, luceneDirectory, fieldDefinitions, analyzer, null, null) | |
{ | |
_luceneIndexDiagnostics = new LuceneIndexDiagnostics(this, profilingLogger); | |
} | |
// create a reference to a pre-built index diagnostics for lucene indexes | |
private readonly LuceneIndexDiagnostics _luceneIndexDiagnostics; | |
//wrap results | |
public int DocumentCount => _luceneIndexDiagnostics.DocumentCount; | |
public int FieldCount => _luceneIndexDiagnostics.FieldCount; | |
public IReadOnlyDictionary<string, object> Metadata => _luceneIndexDiagnostics.Metadata; | |
public Attempt<string> IsHealthy() => _luceneIndexDiagnostics.IsHealthy(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Creates and registers custom indexes on startup | |
/// </summary> | |
public class ProductIndexComponent : IComponent | |
{ | |
private readonly IExamineManager _examineManager; | |
private readonly ProductIndexCreator _productIndexCreator; | |
public ProductIndexComponent(IExamineManager examineManager, ProductIndexCreator productIndexCreator) | |
{ | |
_examineManager = examineManager; | |
_productIndexCreator = productIndexCreator; | |
} | |
public void Initialize() | |
{ | |
foreach (var index in _productIndexCreator.Create()) | |
_examineManager.AddIndex(index); | |
} | |
public void Terminate() { } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Registers all components and services for custom indexes | |
/// </summary> | |
[RuntimeLevel(MinLevel = RuntimeLevel.Run)] | |
public class ProductIndexComposer : IUserComposer | |
{ | |
public void Compose(Composition composition) | |
{ | |
composition.Components().Append<ProductIndexComponent>(); | |
composition.RegisterUnique<ProductIndexValueSetBuilder>(); | |
composition.Register<ProductIndexPopulator>(Lifetime.Singleton); | |
composition.RegisterUnique<ProductIndexCreator>(); | |
composition.RegisterUnique<IProductService, ProductService>(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Factory to create the custom index | |
/// </summary> | |
public class ProductIndexCreator : LuceneIndexCreator | |
{ | |
private readonly IProfilingLogger _logger; | |
public ProductIndexCreator(IProfilingLogger logger) | |
{ | |
_logger = logger; | |
} | |
public override IEnumerable<IIndex> Create() | |
{ | |
var index = new ProductIndex("ProductIndex", | |
CreateFileSystemLuceneDirectory("ProductIndex"), | |
new FieldDefinitionCollection( | |
new FieldDefinition("name", FieldDefinitionTypes.FullTextSortable), | |
new FieldDefinition("price", FieldDefinitionTypes.FullText) | |
), | |
new StandardAnalyzer(Version.LUCENE_30), | |
_logger); | |
return new[] { index }; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Populates the custom index with data when it needs to be rebuilt | |
/// </summary> | |
public class ProductIndexPopulator : IndexPopulator | |
{ | |
private readonly ProductIndexValueSetBuilder _productValueSetBuilder; | |
private readonly IProductService _productService; | |
public ProductIndexPopulator(ProductIndexValueSetBuilder productValueSetBuilder, IProductService productService) | |
{ | |
_productValueSetBuilder = productValueSetBuilder; | |
_productService = productService; | |
RegisterIndex("ProductIndex"); | |
} | |
protected override void PopulateIndexes(IReadOnlyList<IIndex> indexes) | |
{ | |
var products = _productService.GetAll().ToArray(); | |
foreach (var index in indexes) | |
{ | |
index.IndexItems(_productValueSetBuilder.GetValueSets(products)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Converts <see cref="Product"/> to Examine ValueSet's | |
/// </summary> | |
public class ProductIndexValueSetBuilder : IValueSetBuilder<Product> | |
{ | |
public IEnumerable<ValueSet> GetValueSets(params Product[] products) | |
{ | |
foreach (var product in products) | |
{ | |
var indexValues = new Dictionary<string, object> | |
{ | |
["name"] = product.Name, | |
["price"] = product.Price | |
}; | |
var valueSet = new ValueSet(product.Id.ToString(), "product", indexValues); | |
yield return valueSet; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Implementation of IProductService | |
/// </summary> | |
public class ProductService : IProductService | |
{ | |
public IEnumerable<Product> GetAll() | |
{ | |
//mock data | |
yield return new Product { Id = System.Guid.NewGuid(), Name = "Hello", Price = 13.50 }; | |
yield return new Product { Id = System.Guid.NewGuid(), Name = "World", Price = 10.12 }; | |
yield return new Product { Id = System.Guid.NewGuid(), Name = "Hi", Price = 100.99 }; | |
yield return new Product { Id = System.Guid.NewGuid(), Name = "There", Price = 1000.20 }; | |
} | |
} |
@Shazwazza yes, unfortunately we can't pass in e.g. Dictionary<string, object> or similar with some additional data to GetValueSets()
since the signature of the method doesn't allow this, so it has to be part of the entity/item itself.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi all - these examples were made a long time ago and I'm not really maintaining them - they should all be ported to real documentation. Feel free to help out with that if you can. For Umbraco based stuff it should be in https://github.com/umbraco/UmbracoDocs for Examine specific (non-umbraco related), docs are here https://shazwazza.github.io/Examine/
@gdiazderadaa
The definition collection is not a filter. It just defines the field types. Examine 1.x will index all data that is passed to it in value sets. This is different from 0.x where it would only index fields that you 'define'. You can filter fields with the validator or on events.
@bjarnef
The code above is just examples, you are in charge of this code. If you want to add any functionality you're free to do so.
ProductIndexValueSetBuilder
is just a custom service, you can use whatever you want to create value sets.