mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-21 03:14:10 +08:00
Incremental work on multiple indexes
--HG-- branch : 1.x extra : rebase_source : 39da1f112307ff02bf7a01ecabc95a43271d476c
This commit is contained in:
@@ -111,7 +111,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
|
|
||||||
var thingType = new ContentTypeDefinitionBuilder()
|
var thingType = new ContentTypeDefinitionBuilder()
|
||||||
.Named(ThingDriver.ContentTypeName)
|
.Named(ThingDriver.ContentTypeName)
|
||||||
.WithSetting("TypeIndexing.Included", "true")
|
.WithSetting("TypeIndexing.Indexes", "Search")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_contentDefinitionManager
|
_contentDefinitionManager
|
||||||
@@ -145,7 +145,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
public void ShouldNotIndexContentIfIndexDocumentIsEmpty() {
|
public void ShouldNotIndexContentIfIndexDocumentIsEmpty() {
|
||||||
var alphaType = new ContentTypeDefinitionBuilder()
|
var alphaType = new ContentTypeDefinitionBuilder()
|
||||||
.Named("alpha")
|
.Named("alpha")
|
||||||
.WithSetting("TypeIndexing.Included", "true") // the content types should be indexed, but there is no content at all
|
.WithSetting("TypeIndexing.Indexes", "Search") // the content types should be indexed, but there is no content at all
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_contentDefinitionManager
|
_contentDefinitionManager
|
||||||
|
@@ -6,4 +6,5 @@ Version: 1.6
|
|||||||
OrchardVersion: 1.4.1
|
OrchardVersion: 1.4.1
|
||||||
Description: The Lucene module enables the site to be indexed using Lucene.NET. The index generated by this module can then be used by the search module to provide an integrated full-text search experience to a web site.
|
Description: The Lucene module enables the site to be indexed using Lucene.NET. The index generated by this module can then be used by the search module to provide an integrated full-text search experience to a web site.
|
||||||
FeatureDescription: Lucene indexing services.
|
FeatureDescription: Lucene indexing services.
|
||||||
|
Dependencies: Orchard.Indexing
|
||||||
Category: Search
|
Category: Search
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Orchard.Commands;
|
using Orchard.Commands;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.ContentManagement.Aspects;
|
|
||||||
using Orchard.Indexing.Services;
|
using Orchard.Indexing.Services;
|
||||||
using Orchard.Tasks.Indexing;
|
using Orchard.Tasks.Indexing;
|
||||||
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
namespace Orchard.Indexing.Commands {
|
namespace Orchard.Indexing.Commands {
|
||||||
public class IndexingCommands : DefaultOrchardCommandHandler {
|
public class IndexingCommands : DefaultOrchardCommandHandler {
|
||||||
@@ -12,7 +12,6 @@ namespace Orchard.Indexing.Commands {
|
|||||||
private readonly IIndexingService _indexingService;
|
private readonly IIndexingService _indexingService;
|
||||||
private readonly IIndexingTaskManager _indexingTaskManager;
|
private readonly IIndexingTaskManager _indexingTaskManager;
|
||||||
private readonly IContentManager _contentManager;
|
private readonly IContentManager _contentManager;
|
||||||
private const string SearchIndexName = "Search";
|
|
||||||
|
|
||||||
public IndexingCommands(
|
public IndexingCommands(
|
||||||
IIndexManager indexManager,
|
IIndexManager indexManager,
|
||||||
@@ -31,29 +30,66 @@ namespace Orchard.Indexing.Commands {
|
|||||||
[OrchardSwitch]
|
[OrchardSwitch]
|
||||||
public string ContentItem { get; set; }
|
public string ContentItem { get; set; }
|
||||||
|
|
||||||
|
[CommandName("index create")]
|
||||||
|
[CommandHelp("index create <index>\r\n\t" + "Creates a new index with the specified name")]
|
||||||
|
public void Create(string index) {
|
||||||
|
if (!_indexManager.HasIndexProvider()) {
|
||||||
|
Context.Output.WriteLine(T("No index service available"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.ToSafeName() != index) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_indexManager.GetSearchIndexProvider().CreateIndex(index);
|
||||||
|
Context.Output.WriteLine(T("New index has been created succeffully."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[CommandName("index update")]
|
[CommandName("index update")]
|
||||||
[CommandHelp("index update\r\n\t" + "Updates the search index")]
|
[CommandHelp("index update <index>\r\n\t" + "Updates the specified index")]
|
||||||
public void Update() {
|
public void Update(string index) {
|
||||||
_indexingService.UpdateIndex(SearchIndexName);
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_indexingService.UpdateIndex(index);
|
||||||
Context.Output.WriteLine(T("Index is now being updated..."));
|
Context.Output.WriteLine(T("Index is now being updated..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandName("index rebuild")]
|
[CommandName("index rebuild")]
|
||||||
[CommandHelp("index rebuild \r\n\t" + "Rebuilds the search index")]
|
[CommandHelp("index rebuild <index> \r\n\t" + "Rebuilds the specified index")]
|
||||||
public void Rebuild() {
|
public void Rebuild(string index) {
|
||||||
_indexingService.RebuildIndex(SearchIndexName);
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_indexingService.RebuildIndex(index);
|
||||||
Context.Output.WriteLine(T("Index is now being rebuilt..."));
|
Context.Output.WriteLine(T("Index is now being rebuilt..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandName("index search")]
|
[CommandName("index query")]
|
||||||
[CommandHelp("index search /Query:<query>\r\n\t" + "Searches the specified <query> terms in the search index")]
|
[CommandHelp("index query <index> /Query:<query>\r\n\t" + "Searches the specified <query> terms in the specified index")]
|
||||||
[OrchardSwitches("Query")]
|
[OrchardSwitches("Query")]
|
||||||
public void Search() {
|
public void Search(string index) {
|
||||||
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !_indexManager.HasIndexProvider() ) {
|
if ( !_indexManager.HasIndexProvider() ) {
|
||||||
Context.Output.WriteLine(T("No index available"));
|
Context.Output.WriteLine(T("No index available"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(SearchIndexName);
|
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(index);
|
||||||
var results = searchBuilder.Parse( new [] {"body", "title"}, Query).Search();
|
var results = searchBuilder.Parse( new [] {"body", "title"}, Query).Search();
|
||||||
|
|
||||||
Context.Output.WriteLine("{0} result{1}\r\n-----------------\r\n", results.Count(), results.Count() > 0 ? "s" : "");
|
Context.Output.WriteLine("{0} result{1}\r\n-----------------\r\n", results.Count(), results.Count() > 0 ? "s" : "");
|
||||||
@@ -76,15 +112,20 @@ namespace Orchard.Indexing.Commands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[CommandName("index stats")]
|
[CommandName("index stats")]
|
||||||
[CommandHelp("index stats\r\n\t" + "Displays some statistics about the search index")]
|
[CommandHelp("index stats <index>\r\n\t" + "Displays some statistics about the search index")]
|
||||||
[OrchardSwitches("IndexName")]
|
[OrchardSwitches("IndexName")]
|
||||||
public void Stats() {
|
public void Stats(string index) {
|
||||||
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !_indexManager.HasIndexProvider() ) {
|
if ( !_indexManager.HasIndexProvider() ) {
|
||||||
Context.Output.WriteLine(T("No index available"));
|
Context.Output.WriteLine(T("No index available"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.Output.WriteLine(T("Number of indexed documents: {0}", _indexManager.GetSearchIndexProvider().NumDocs(SearchIndexName)));
|
Context.Output.WriteLine(T("Number of indexed documents: {0}", _indexManager.GetSearchIndexProvider().NumDocs(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandName("index refresh")]
|
[CommandName("index refresh")]
|
||||||
|
@@ -15,5 +15,8 @@ namespace Orchard.Indexing {
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: When upgrading from 1, change TypeIndexing.Included to TypeIndexing.Indexes = "Search"
|
||||||
|
// todo: When upgrading from 1, define SearchSettingsPart.SelectedIndex to "Search"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -68,7 +68,7 @@ namespace Orchard.Indexing.Services
|
|||||||
handler.UpdateIndex(indexName);
|
handler.UpdateIndex(indexName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.Notifier.Information(T("The search index has been updated."));
|
Services.Notifier.Information(T("The index {0} has been updated.", indexName));
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexEntry IIndexingService.GetIndexEntry(string indexName) {
|
IndexEntry IIndexingService.GetIndexEntry(string indexName) {
|
||||||
|
@@ -166,6 +166,13 @@ namespace Orchard.Indexing.Services {
|
|||||||
|
|
||||||
foreach (var item in contentItems) {
|
foreach (var item in contentItems) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// skip items from types which are not indexed
|
||||||
|
var settings = GetTypeIndexingSettings(item);
|
||||||
|
if (!settings.Indexes.Contains(indexName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
IDocumentIndex documentIndex = ExtractDocumentIndex(item);
|
IDocumentIndex documentIndex = ExtractDocumentIndex(item);
|
||||||
|
|
||||||
if (documentIndex != null && documentIndex.IsDirty) {
|
if (documentIndex != null && documentIndex.IsDirty) {
|
||||||
@@ -195,8 +202,17 @@ namespace Orchard.Indexing.Services {
|
|||||||
|
|
||||||
foreach (var item in indexingTasks) {
|
foreach (var item in indexingTasks) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
IDocumentIndex documentIndex = null;
|
||||||
|
|
||||||
// item.ContentItem can be null if the content item has been deleted
|
// item.ContentItem can be null if the content item has been deleted
|
||||||
IDocumentIndex documentIndex = ExtractDocumentIndex(item.ContentItem);
|
if (item.ContentItem != null) {
|
||||||
|
// skip items from types which are not indexed
|
||||||
|
var settings = GetTypeIndexingSettings(item.ContentItem);
|
||||||
|
if (!settings.Indexes.Contains(indexName)) {
|
||||||
|
documentIndex = ExtractDocumentIndex(item.ContentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (documentIndex == null || item.Delete) {
|
if (documentIndex == null || item.Delete) {
|
||||||
deleteFromIndex.Add(item.Id);
|
deleteFromIndex.Add(item.Id);
|
||||||
@@ -284,12 +300,6 @@ namespace Orchard.Indexing.Services {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip items from types which are not indexed
|
|
||||||
var settings = GetTypeIndexingSettings(contentItem);
|
|
||||||
if (!settings.Included) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var documentIndex = _indexProvider.New(contentItem.Id);
|
var documentIndex = _indexProvider.New(contentItem.Id);
|
||||||
|
|
||||||
// call all handlers to add content to index
|
// call all handlers to add content to index
|
||||||
@@ -301,7 +311,7 @@ namespace Orchard.Indexing.Services {
|
|||||||
if (contentItem == null ||
|
if (contentItem == null ||
|
||||||
contentItem.TypeDefinition == null ||
|
contentItem.TypeDefinition == null ||
|
||||||
contentItem.TypeDefinition.Settings == null) {
|
contentItem.TypeDefinition.Settings == null) {
|
||||||
return new TypeIndexing {Included = false};
|
return new TypeIndexing {Indexes = ""};
|
||||||
}
|
}
|
||||||
return contentItem.TypeDefinition.Settings.GetModel<TypeIndexing>();
|
return contentItem.TypeDefinition.Settings.GetModel<TypeIndexing>();
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.ContentManagement.MetaData;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.ContentManagement.MetaData.Builders;
|
using Orchard.ContentManagement.MetaData.Builders;
|
||||||
@@ -28,7 +29,7 @@ namespace Orchard.Indexing.Settings {
|
|||||||
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
|
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
|
||||||
var model = new TypeIndexing();
|
var model = new TypeIndexing();
|
||||||
updateModel.TryUpdateModel(model, "TypeIndexing", null, null);
|
updateModel.TryUpdateModel(model, "TypeIndexing", null, null);
|
||||||
builder.WithSetting("TypeIndexing.Included", model.Included ? true.ToString() : null);
|
builder.WithSetting("TypeIndexing.Indexes", model.Indexes);
|
||||||
|
|
||||||
CreateIndexingTasks();
|
CreateIndexingTasks();
|
||||||
|
|
||||||
|
@@ -1,5 +1,12 @@
|
|||||||
namespace Orchard.Indexing.Settings {
|
using System;
|
||||||
|
|
||||||
|
namespace Orchard.Indexing.Settings {
|
||||||
public class TypeIndexing {
|
public class TypeIndexing {
|
||||||
public bool Included { get; set; }
|
public string Indexes { get; set; }
|
||||||
|
|
||||||
|
public string[] List {
|
||||||
|
get { return String.IsNullOrEmpty(Indexes) ? new string[0] : Indexes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); }
|
||||||
|
set { Indexes = String.Join(",", value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
<div>@T("There are no indexes.")</div>
|
<div>@T("There is currently no index.")</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (Model.IndexProvider != null) {
|
@if (Model.IndexProvider != null) {
|
||||||
|
@@ -1,7 +1,21 @@
|
|||||||
@model Orchard.Indexing.Settings.TypeIndexing
|
@using Orchard.Indexing
|
||||||
|
@using Orchard.Utility.Extensions
|
||||||
|
@model Orchard.Indexing.Settings.TypeIndexing
|
||||||
|
@{
|
||||||
|
var indexProvider = WorkContext.Resolve<IIndexManager>().GetSearchIndexProvider();
|
||||||
|
|
||||||
<fieldset>
|
}
|
||||||
@Html.EditorFor(m=>m.Included)
|
|
||||||
<label for="@Html.FieldIdFor(m => m.Included)" class="forcheckbox">@T("Index this content type for search")</label>
|
@if (indexProvider != null) {
|
||||||
@Html.ValidationMessageFor(m=>m.Included)
|
<fieldset>
|
||||||
</fieldset>
|
<legend>@T("Index this content type in:")</legend>
|
||||||
|
@{ var i = 0;}
|
||||||
|
@foreach (var index in indexProvider.List()) {
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" value="@index" class="check-box" id="@Html.FieldIdFor(m => m.List[i])" name="@Html.FieldNameFor(m => m.List)" checked="@(Model.List.Contains(index))"/>
|
||||||
|
<label for="@Html.FieldIdFor(m => m.List[i])" class="forcheckbox">@index</label>
|
||||||
|
</div>
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
</fieldset>
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
using Orchard.Commands;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.Search.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Search.Commands {
|
||||||
|
public class SearchCommands : DefaultOrchardCommandHandler {
|
||||||
|
private readonly IOrchardServices _orchardServices;
|
||||||
|
|
||||||
|
public SearchCommands(IOrchardServices orchardServices) {
|
||||||
|
_orchardServices = orchardServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandName("search use")]
|
||||||
|
[CommandHelp("search use <index>\r\n\t" + "Defines the default index to use for search")]
|
||||||
|
public void Index(string index) {
|
||||||
|
var settings = _orchardServices.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(index)) {
|
||||||
|
Context.Output.WriteLine(T("Invalid index name."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings != null) {
|
||||||
|
settings.SearchIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -36,15 +36,16 @@ namespace Orchard.Search.Controllers {
|
|||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
public ActionResult Index(PagerParameters pagerParameters, string searchText = "") {
|
public ActionResult Index(PagerParameters pagerParameters, string searchText = "") {
|
||||||
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||||
var searchFields = Services.WorkContext.CurrentSite.As<SearchSettingsPart>().SearchedFields;
|
var searchSettingsPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||||
|
|
||||||
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
||||||
try {
|
try {
|
||||||
|
|
||||||
searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize,
|
searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize,
|
||||||
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
||||||
searchFields,
|
searchSettingsPart.SearchIndex,
|
||||||
|
searchSettingsPart.SearchedFields,
|
||||||
searchHit => searchHit);
|
searchHit => searchHit);
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
catch (Exception exception) {
|
||||||
|
@@ -64,7 +64,8 @@ namespace Orchard.Search.Controllers {
|
|||||||
return View("NoIndex");
|
return View("NoIndex");
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search");
|
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(settings.SearchIndex);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
builder.Parse(searchFields, searchText);
|
builder.Parse(searchFields, searchText);
|
||||||
|
|
||||||
|
@@ -46,14 +46,20 @@ namespace Orchard.Search.Controllers {
|
|||||||
|
|
||||||
public ActionResult Index(PagerParameters pagerParameters, string q = "") {
|
public ActionResult Index(PagerParameters pagerParameters, string q = "") {
|
||||||
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||||
var searchFields = Services.WorkContext.CurrentSite.As<SearchSettingsPart>().SearchedFields;
|
var searchSettingPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(searchSettingPart.SearchIndex)) {
|
||||||
|
Services.Notifier.Error(T("Please define a default search index"));
|
||||||
|
return HttpNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
||||||
try {
|
try {
|
||||||
|
|
||||||
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
|
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
|
||||||
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
|
||||||
searchFields,
|
searchSettingPart.SearchIndex,
|
||||||
|
searchSettingPart.SearchedFields,
|
||||||
searchHit => searchHit);
|
searchHit => searchHit);
|
||||||
} catch(Exception exception) {
|
} catch(Exception exception) {
|
||||||
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);
|
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);
|
||||||
|
@@ -11,7 +11,6 @@ using Orchard.Search.ViewModels;
|
|||||||
namespace Orchard.Search.Drivers {
|
namespace Orchard.Search.Drivers {
|
||||||
|
|
||||||
public class SearchSettingsPartDriver : ContentPartDriver<SearchSettingsPart> {
|
public class SearchSettingsPartDriver : ContentPartDriver<SearchSettingsPart> {
|
||||||
private const string SearchIndexName = "Search";
|
|
||||||
private readonly IIndexManager _indexManager;
|
private readonly IIndexManager _indexManager;
|
||||||
|
|
||||||
public SearchSettingsPartDriver(IIndexManager indexManager) {
|
public SearchSettingsPartDriver(IIndexManager indexManager) {
|
||||||
@@ -30,24 +29,33 @@ namespace Orchard.Search.Drivers {
|
|||||||
|
|
||||||
protected override DriverResult Editor(SearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
protected override DriverResult Editor(SearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||||
return ContentShape("Parts_Search_SiteSettings", () => {
|
return ContentShape("Parts_Search_SiteSettings", () => {
|
||||||
SearchSettingsViewModel model = new SearchSettingsViewModel();
|
var model = new SearchSettingsViewModel();
|
||||||
String[] searchedFields = part.SearchedFields;
|
String[] searchedFields = part.SearchedFields;
|
||||||
|
|
||||||
if (updater != null) {
|
if (updater != null) {
|
||||||
// submitting: rebuild model from form data
|
// submitting: rebuild model from form data
|
||||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||||
// update part if successful
|
// update part if successful
|
||||||
part.SearchedFields = model.Entries.Where(e => e.Selected).Select(e => e.Field).ToArray();
|
part.SearchIndex = model.SelectedIndex;
|
||||||
|
part.SearchedFields = model.Entries.First(e => e.Index == model.SelectedIndex).Fields.Where(e => e.Selected).Select(e => e.Field).ToArray();
|
||||||
part.FilterCulture = model.FilterCulture;
|
part.FilterCulture = model.FilterCulture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_indexManager.HasIndexProvider()) {
|
else if (_indexManager.HasIndexProvider()) {
|
||||||
// viewing editor: build model from part
|
// viewing editor: build model from part
|
||||||
model.FilterCulture = part.FilterCulture;
|
model.FilterCulture = part.FilterCulture;
|
||||||
model.Entries = new List<SearchSettingsEntry>();
|
model.SelectedIndex = part.SearchIndex;
|
||||||
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(SearchIndexName)) {
|
model.Entries = _indexManager.GetSearchIndexProvider().List().Select(x => {
|
||||||
model.Entries.Add(new SearchSettingsEntry { Field = field, Selected = searchedFields.Contains(field) });
|
var indexSettings = new IndexSettingsEntry {
|
||||||
}
|
Index = x,
|
||||||
|
Fields = new List<SearchSettingsEntry>()
|
||||||
|
};
|
||||||
|
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
|
||||||
|
indexSettings.Fields.Add(new SearchSettingsEntry {Field = field, Selected = (x == part.SearchIndex && searchedFields.Contains(field))});
|
||||||
|
}
|
||||||
|
|
||||||
|
return indexSettings;
|
||||||
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings", Model: model, Prefix: Prefix);
|
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings", Model: model, Prefix: Prefix);
|
||||||
|
@@ -10,6 +10,7 @@ namespace Orchard.Search {
|
|||||||
.ContentPartRecord()
|
.ContentPartRecord()
|
||||||
.Column<bool>("FilterCulture")
|
.Column<bool>("FilterCulture")
|
||||||
.Column<string>("SearchedFields", c => c.Unlimited())
|
.Column<string>("SearchedFields", c => c.Unlimited())
|
||||||
|
.Column<string>("SearchIndex")
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentDefinitionManager.AlterTypeDefinition("SearchForm",
|
ContentDefinitionManager.AlterTypeDefinition("SearchForm",
|
||||||
@@ -20,7 +21,15 @@ namespace Orchard.Search {
|
|||||||
.WithSetting("Stereotype", "Widget")
|
.WithSetting("Stereotype", "Widget")
|
||||||
);
|
);
|
||||||
|
|
||||||
return 1;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UpdateFrom1() {
|
||||||
|
SchemaBuilder.AlterTable("SearchSettingsPartRecord", table => table
|
||||||
|
.AddColumn<string>("SearchIndex")
|
||||||
|
);
|
||||||
|
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -12,5 +12,10 @@ namespace Orchard.Search.Models {
|
|||||||
get { return Record.FilterCulture; }
|
get { return Record.FilterCulture; }
|
||||||
set { Record.FilterCulture = value; }
|
set { Record.FilterCulture = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SearchIndex {
|
||||||
|
get { return Record.SearchIndex; }
|
||||||
|
set { Record.SearchIndex = value; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,12 +2,13 @@ using Orchard.ContentManagement.Records;
|
|||||||
|
|
||||||
namespace Orchard.Search.Models {
|
namespace Orchard.Search.Models {
|
||||||
public class SearchSettingsPartRecord : ContentPartRecord {
|
public class SearchSettingsPartRecord : ContentPartRecord {
|
||||||
public virtual bool FilterCulture { get; set; }
|
|
||||||
public virtual string SearchedFields { get; set; }
|
|
||||||
|
|
||||||
public SearchSettingsPartRecord() {
|
public SearchSettingsPartRecord() {
|
||||||
FilterCulture = false;
|
FilterCulture = false;
|
||||||
SearchedFields = "body, title";
|
SearchedFields = "body, title";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual bool FilterCulture { get; set; }
|
||||||
|
public virtual string SearchedFields { get; set; }
|
||||||
|
public virtual string SearchIndex { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -47,6 +47,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
<Reference Include="System.Core">
|
<Reference Include="System.Core">
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Commands\SearchCommands.cs" />
|
||||||
<Compile Include="ContentPickerNavigationProvider.cs" />
|
<Compile Include="ContentPickerNavigationProvider.cs" />
|
||||||
<Compile Include="Controllers\ContentPickerController.cs" />
|
<Compile Include="Controllers\ContentPickerController.cs" />
|
||||||
<Compile Include="ContentAdminMenu.cs" />
|
<Compile Include="ContentAdminMenu.cs" />
|
||||||
@@ -87,6 +89,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Module.txt" />
|
<Content Include="Module.txt" />
|
||||||
|
<Content Include="Recipes\Search.recipe.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
<Content Include="Styles\orchard-search-admin.css" />
|
<Content Include="Styles\orchard-search-admin.css" />
|
||||||
<Content Include="Styles\orchard-search-search.css" />
|
<Content Include="Styles\orchard-search-search.css" />
|
||||||
<Content Include="Views\Web.config" />
|
<Content Include="Views\Web.config" />
|
||||||
|
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<Orchard>
|
||||||
|
<Recipe>
|
||||||
|
<Name>Search</Name>
|
||||||
|
<Description>Configures a default search index and search settings using the Lucene engine.</Description>
|
||||||
|
<Author>The Orchard Team</Author>
|
||||||
|
<WebSite>http://orchardproject.net</WebSite>
|
||||||
|
<Tags>developer</Tags>
|
||||||
|
<Version>1.0</Version>
|
||||||
|
</Recipe>
|
||||||
|
|
||||||
|
<Feature enable="Orchard.Search,Lucene" />
|
||||||
|
|
||||||
|
<Metadata>
|
||||||
|
<Types>
|
||||||
|
<Page TypeIndexing.Indexes="Search">
|
||||||
|
</Page>
|
||||||
|
<BlogPost TypeIndexing.Indexes="Search">
|
||||||
|
</BlogPost>
|
||||||
|
</Types>
|
||||||
|
</Metadata>
|
||||||
|
|
||||||
|
<Migration features="*" />
|
||||||
|
|
||||||
|
<Command>
|
||||||
|
index create Search
|
||||||
|
index update Search
|
||||||
|
search use Search
|
||||||
|
</Command>
|
||||||
|
</Orchard>
|
@@ -4,6 +4,6 @@ using Orchard.Indexing;
|
|||||||
|
|
||||||
namespace Orchard.Search.Services {
|
namespace Orchard.Search.Services {
|
||||||
public interface ISearchService : IDependency {
|
public interface ISearchService : IDependency {
|
||||||
IPageOfItems<T> Query<T>(string query, int skip, int? take, bool filterCulture, string[] searchFields, Func<ISearchHit, T> shapeResult);
|
IPageOfItems<T> Query<T>(string query, int skip, int? take, bool filterCulture, string index, string[] searchFields, Func<ISearchHit, T> shapeResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -21,18 +21,18 @@ namespace Orchard.Search.Services {
|
|||||||
public IOrchardServices Services { get; set; }
|
public IOrchardServices Services { get; set; }
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
ISearchBuilder Search() {
|
ISearchBuilder Search(string index) {
|
||||||
return _indexManager.HasIndexProvider()
|
return _indexManager.HasIndexProvider()
|
||||||
? _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search")
|
? _indexManager.GetSearchIndexProvider().CreateSearchBuilder(index)
|
||||||
: new NullSearchBuilder();
|
: new NullSearchBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
IPageOfItems<T> ISearchService.Query<T>(string query, int page, int? pageSize, bool filterCulture, string[] searchFields, Func<ISearchHit, T> shapeResult) {
|
IPageOfItems<T> ISearchService.Query<T>(string query, int page, int? pageSize, bool filterCulture, string index, string[] searchFields, Func<ISearchHit, T> shapeResult) {
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(query))
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
return new PageOfItems<T>(Enumerable.Empty<T>());
|
return new PageOfItems<T>(Enumerable.Empty<T>());
|
||||||
|
|
||||||
var searchBuilder = Search().Parse(searchFields, query);
|
var searchBuilder = Search(index).Parse(searchFields, query);
|
||||||
|
|
||||||
if (filterCulture) {
|
if (filterCulture) {
|
||||||
var culture = _cultureManager.GetSiteCulture();
|
var culture = _cultureManager.GetSiteCulture();
|
||||||
|
@@ -26,6 +26,7 @@ namespace Orchard.Search.Settings {
|
|||||||
var model = new ContentPickerSearchFieldSettings();
|
var model = new ContentPickerSearchFieldSettings();
|
||||||
if (updateModel.TryUpdateModel(model, "ContentPickerSearchFieldSettings", null, null)) {
|
if (updateModel.TryUpdateModel(model, "ContentPickerSearchFieldSettings", null, null)) {
|
||||||
builder.WithSetting("ContentPickerSearchFieldSettings.ShowSearchTab", model.ShowSearchTab.ToString(CultureInfo.InvariantCulture));
|
builder.WithSetting("ContentPickerSearchFieldSettings.ShowSearchTab", model.ShowSearchTab.ToString(CultureInfo.InvariantCulture));
|
||||||
|
builder.WithSetting("ContentPickerSearchFieldSettings.SearchIndex", model.SearchIndex);
|
||||||
builder.WithSetting("ContentPickerSearchFieldSettings.DisplayedContentTypes", model.DisplayedContentTypes);
|
builder.WithSetting("ContentPickerSearchFieldSettings.DisplayedContentTypes", model.DisplayedContentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool ShowSearchTab { get; set; }
|
public bool ShowSearchTab { get; set; }
|
||||||
|
public string SearchIndex { get; set; }
|
||||||
public string DisplayedContentTypes { get; set; }
|
public string DisplayedContentTypes { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,16 @@
|
|||||||
|
|
||||||
namespace Orchard.Search.ViewModels {
|
namespace Orchard.Search.ViewModels {
|
||||||
public class SearchSettingsViewModel {
|
public class SearchSettingsViewModel {
|
||||||
public IList<SearchSettingsEntry> Entries { get; set; }
|
public string SelectedIndex { get; set; }
|
||||||
|
public IList<IndexSettingsEntry> Entries { get; set; }
|
||||||
public bool FilterCulture { get; set; }
|
public bool FilterCulture { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class IndexSettingsEntry {
|
||||||
|
public string Index { get; set; }
|
||||||
|
public IList<SearchSettingsEntry> Fields { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class SearchSettingsEntry {
|
public class SearchSettingsEntry {
|
||||||
public string Field { get; set; }
|
public string Field { get; set; }
|
||||||
public bool Selected { get; set; }
|
public bool Selected { get; set; }
|
||||||
|
@@ -1,4 +1,9 @@
|
|||||||
@model Orchard.Search.Settings.ContentPickerSearchFieldSettings
|
@using Orchard.Indexing
|
||||||
|
@model Orchard.Search.Settings.ContentPickerSearchFieldSettings
|
||||||
|
@{
|
||||||
|
var indexManager = WorkContext.Resolve<IIndexManager>();
|
||||||
|
var indexProvider = indexManager.GetSearchIndexProvider();
|
||||||
|
}
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div>
|
<div>
|
||||||
@@ -7,6 +12,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
<div>
|
||||||
|
<label for="@Html.FieldIdFor(m => m.SearchIndex)">@T("Search index")</label>
|
||||||
|
<select name="@Html.FieldNameFor(m => m.SearchIndex)" >
|
||||||
|
@foreach (string index in indexProvider.List()) {
|
||||||
|
@Html.SelectOption(Model.SearchIndex, index, index)
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<span class="hint">@T("The index to use when displaying this tab.")</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="@Html.FieldIdFor(m => m.DisplayedContentTypes)">@T("Content Types and Parts")</label>
|
<label for="@Html.FieldIdFor(m => m.DisplayedContentTypes)">@T("Content Types and Parts")</label>
|
||||||
@Html.TextBoxFor(m => m.DisplayedContentTypes)
|
@Html.TextBoxFor(m => m.DisplayedContentTypes)
|
||||||
|
@@ -1,28 +1,55 @@
|
|||||||
@model Orchard.Search.ViewModels.SearchSettingsViewModel
|
@using Orchard.Search.ViewModels
|
||||||
@using Orchard.Search.ViewModels;
|
@model Orchard.Search.ViewModels.SearchSettingsViewModel
|
||||||
|
@{
|
||||||
|
Script.Require("jQuery");
|
||||||
|
|
||||||
|
}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>@T("Search")</legend>
|
<legend>@T("Search")</legend>
|
||||||
<div>
|
<div>
|
||||||
<label>@T("Searched fields")</label>
|
<label>@T("Indexes")</label>
|
||||||
<span class="hint">@T("Check any property which should be used for search queries.")</span>
|
|
||||||
@{var entryIndex = 0;}
|
|
||||||
|
|
||||||
@if (Model.Entries != null && Model.Entries.Any()) {
|
@if (Model.Entries != null && Model.Entries.Any()) {
|
||||||
<ul>
|
if (String.IsNullOrWhiteSpace(Model.SelectedIndex)) {
|
||||||
@foreach(var modelEntry in Model.Entries) {
|
Model.Entries.Insert(0, new IndexSettingsEntry { Index = "" });
|
||||||
<li>
|
|
||||||
@Html.EditorFor(m => m.Entries[entryIndex].Selected)
|
|
||||||
@Html.HiddenFor(m => m.Entries[entryIndex].Field)
|
|
||||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndex].Selected)">@Model.Entries[entryIndex].Field</label>
|
|
||||||
</li>
|
|
||||||
entryIndex = entryIndex + 1;
|
|
||||||
}
|
}
|
||||||
</ul>
|
|
||||||
|
<select id="selectIndex" name="@Html.NameFor(m => m.SelectedIndex)">
|
||||||
|
@foreach (var modelEntry in Model.Entries) {
|
||||||
|
@Html.SelectOption(Model.SelectedIndex, modelEntry.Index, modelEntry.Index)
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<span class="hint">@T("Select which index to use in search queries.")</span>
|
||||||
|
|
||||||
|
<label>@T("Fields")</label>
|
||||||
|
<ul>
|
||||||
|
@{var entryIndex = 0;}
|
||||||
|
@foreach(var modelEntry in Model.Entries) {
|
||||||
|
@Html.HiddenFor(m => m.Entries[entryIndex].Index)
|
||||||
|
<li data-index="@modelEntry.Index">
|
||||||
|
@if (modelEntry.Fields != null && modelEntry.Fields.Any()) {
|
||||||
|
<ul>
|
||||||
|
@{ var fieldIndex = 0;}
|
||||||
|
@foreach (var fieldEntry in Model.Entries[entryIndex].Fields) {
|
||||||
|
<li>
|
||||||
|
@Html.EditorFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)
|
||||||
|
@Html.HiddenFor(m => m.Entries[entryIndex].Fields[fieldIndex].Field)
|
||||||
|
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)">@Model.Entries[entryIndex].Fields[fieldIndex].Field</label>
|
||||||
|
</li>
|
||||||
|
fieldIndex++;
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
entryIndex++;
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
<span class="hint">@T("Check any property which should be used for search queries.")</span>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
<span class="hint">@T("There are currently no fields to search from. Please update you index, and check some indexable content exists.")</span>
|
<span class="hint">@T("There is currently no index to search from. Please update you index, and check some indexable content exists.")</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -33,3 +60,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
@using (Script.Foot()) {
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
(function ($) {
|
||||||
|
|
||||||
|
$('li[data-index]').hide();
|
||||||
|
$("li[data-index='@Model.SelectedIndex']").show();
|
||||||
|
$('#selectIndex').change(function () {
|
||||||
|
$('li[data-index]').hide();
|
||||||
|
$("li[data-index='" + $(this).val() + "']").show();
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
}
|
@@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<Types>
|
<Types>
|
||||||
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
|
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||||
<TagsPart />
|
<TagsPart />
|
||||||
<LocalizationPart />
|
<LocalizationPart />
|
||||||
<AutoroutePart />
|
<AutoroutePart />
|
||||||
</Page>
|
</Page>
|
||||||
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
|
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||||
<CommentsPart />
|
<CommentsPart />
|
||||||
<TagsPart />
|
<TagsPart />
|
||||||
<LocalizationPart />
|
<LocalizationPart />
|
||||||
|
@@ -18,13 +18,13 @@
|
|||||||
|
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<Types>
|
<Types>
|
||||||
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
|
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||||
<TagsPart />
|
<TagsPart />
|
||||||
<LocalizationPart />
|
<LocalizationPart />
|
||||||
<TitlePart/>
|
<TitlePart/>
|
||||||
<AutoroutePart />
|
<AutoroutePart />
|
||||||
</Page>
|
</Page>
|
||||||
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
|
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
|
||||||
<CommentsPart />
|
<CommentsPart />
|
||||||
<TagsPart />
|
<TagsPart />
|
||||||
<LocalizationPart />
|
<LocalizationPart />
|
||||||
|
@@ -13,11 +13,11 @@ namespace Orchard.Indexing {
|
|||||||
#region IIndexManager Members
|
#region IIndexManager Members
|
||||||
|
|
||||||
public bool HasIndexProvider() {
|
public bool HasIndexProvider() {
|
||||||
return _indexProviders.AsQueryable().Count() > 0;
|
return _indexProviders.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IIndexProvider GetSearchIndexProvider() {
|
public IIndexProvider GetSearchIndexProvider() {
|
||||||
return _indexProviders.AsQueryable().FirstOrDefault();
|
return _indexProviders.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace Orchard.Indexing {
|
namespace Orchard.Indexing {
|
||||||
public static class MetaDataExtensions {
|
public static class MetaDataExtensions {
|
||||||
public static ContentTypeDefinitionBuilder Indexed(this ContentTypeDefinitionBuilder builder) {
|
public static ContentTypeDefinitionBuilder Indexed(this ContentTypeDefinitionBuilder builder, params string[] indexes) {
|
||||||
return builder.WithSetting("TypeIndexing.Included", "true");
|
return builder.WithSetting("TypeIndexing.Indexes", string.Join(",", indexes ?? new string[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user