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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 }; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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.