Umbraco:基于EBS的AWS弹性负载均衡下自定义Examine索引实现示例求助
我刚好有过类似的Umbraco自定义Examine索引的实现经验,给你分享几个关键的步骤和示例,帮你确保这个KeywordsIndexer能在AWS EBS的ELB环境下正常工作:
1. 实现自定义DataService(ParagraphKeywordIndexer)
你的配置里指定了dataService="SearchIndexers.ParagraphKeywordIndexer",这个类需要实现ISimpleDataService接口,负责提供要索引的业务数据。以下是适配Umbraco 9+的示例(Umbraco 8的话依赖注入方式略有不同,但核心逻辑一致):
using Examine.LuceneEngine.Providers; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Web.Common; namespace SearchIndexers { public class ParagraphKeywordIndexer : ISimpleDataService { private readonly UmbracoContextFactory _umbracoContextFactory; private readonly IContentService _contentService; // 通过构造函数注入Umbraco核心服务 public ParagraphKeywordIndexer(UmbracoContextFactory umbracoContextFactory, IContentService contentService) { _umbracoContextFactory = umbracoContextFactory; _contentService = contentService; } public IEnumerable<SimpleDataSet> GetAllData(string indexType) { // 只处理配置中指定的indexTypes="KeywordIndexItem" if (indexType != "KeywordIndexItem") yield break; // 这里替换成你实际要索引的内容类型,比如"Paragraph"文档类型 var targetContents = _contentService.GetContentOfType("Paragraph"); foreach (var content in targetContents) { // 提取需要索引的字段,字段别名要和你的Umbraco文档类型字段一致 var dataSet = new SimpleDataSet { NodeDefinition = new NodeDefinition { NodeId = content.Id, NodeTypeAlias = content.ContentType.Alias, ParentId = content.ParentId }, RowData = new Dictionary<string, string> { ["id"] = content.Id.ToString(), ["keywords"] = content.Value<string>("keywords") ?? string.Empty, ["title"] = content.Value<string>("pageTitle") ?? string.Empty, ["bodyContent"] = content.Value<string>("bodyText") ?? string.Empty } }; yield return dataSet; } } } }
2. 完善IndexSet配置(KeywordsIndexSet)
你需要在ExamineIndex.config中添加对应的IndexSet配置,明确要索引的字段和基础规则:
<IndexSet SetName="KeywordsIndexSet" IndexPath="~/App_Data/TEMP/ExamineIndexes/KeywordsIndex/"> <IndexAttributeFields> <add Name="id" /> <add Name="keywords" /> <add Name="title" /> <add Name="bodyContent" /> </IndexAttributeFields> <IncludeNodeTypes> <add Name="KeywordIndexItem" /> </IncludeNodeTypes> </IndexSet>
因为你配置了TempEnvDirectoryFactory,这个IndexPath会被自动替换为服务器临时目录,刚好适配AWS EBS的弹性环境,不用担心持久化存储的问题。
3. 测试索引构建与搜索功能
后台手动测试
登录Umbraco后台,进入Settings > Examine Management,找到你的KeywordsSearcher,点击Rebuild Index,查看索引状态是否显示成功。如果失败,可查看Umbraco日志(App_Data/Logs目录)排查错误。
代码层面测试
可以写一个简单的搜索服务类,验证索引是否能正常返回结果:
using Examine; using Umbraco.Cms.Core.Examine; public class KeywordSearchService { private readonly IExamineManager _examineManager; public KeywordSearchService(IExamineManager examineManager) { _examineManager = examineManager; } public IEnumerable<ISearchResult> SearchKeywords(string queryText) { if (!_examineManager.TryGetSearcher("KeywordsSearcher", out var searcher)) { throw new InvalidOperationException("KeywordsSearcher 未找到,请检查Examine配置"); } // 构建搜索条件,这里匹配关键词、标题字段 var criteria = searcher.CreateSearchCriteria("KeywordIndexItem"); var filter = criteria.GroupedOr(new[] { "keywords", "title" }, queryText).Compile(); return searcher.Search(filter); } }
你可以在Umbraco的Api控制器或SurfaceController中注入这个服务,调用后查看返回结果是否符合预期。
4. EBS/ELB环境的特殊注意事项
- 多实例一致性:如果你的Umbraco是多实例部署在ELB下,本地Lucene索引会存在实例间不一致的问题。这种情况推荐改用Examine Cloud,或者替换为AWS OpenSearch这类分布式索引方案;如果是单实例EBS,用
TempEnvDirectoryFactory即可,但要确保实例重启后能触发索引自动重建。 - 权限与存储:确保EBS实例的临时目录有足够的读写权限,Umbraco进程能正常创建和写入索引文件。
- 自动索引更新:配置内容发布/删除时的自动索引更新,避免手动重建:
using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Implement; public class ContentIndexingHandler : IComponent { private readonly IExamineManager _examineManager; private readonly IContentService _contentService; public ContentIndexingHandler(IExamineManager examineManager, IContentService contentService) { _examineManager = examineManager; _contentService = contentService; } public void Initialize() { ContentService.Published += OnContentPublished; ContentService.Deleted += OnContentDeleted; } private void OnContentPublished(IContentService sender, ContentPublishedEventArgs e) { var targetItems = e.PublishedEntities.Where(x => x.ContentType.Alias == "Paragraph"); foreach (var item in targetItems) { if (_examineManager.TryGetIndex("KeywordsIndexer", out var index)) { index.IndexItem(item); } } } private void OnContentDeleted(IContentService sender, ContentDeletedEventArgs e) { var targetItems = e.DeletedEntities.Where(x => x.ContentType.Alias == "Paragraph"); foreach (var item in targetItems) { if (_examineManager.TryGetIndex("KeywordsIndexer", out var index)) { index.DeleteFromIndex(item.Id.ToString()); } } } public void Terminate() { ContentService.Published -= OnContentPublished; ContentService.Deleted -= OnContentDeleted; } }
最后在Umbraco的Startup.cs中注册这个组件,确保内容变更时自动同步索引。
内容的提问来源于stack exchange,提问作者Town
相关产品推荐
相关产品推荐

