Incremental work on multiple indexes

--HG--
branch : 1.x
extra : rebase_source : 39da1f112307ff02bf7a01ecabc95a43271d476c
This commit is contained in:
Sebastien Ros
2013-03-05 11:13:33 -08:00
parent 2015448c44
commit 08972b8cbb
31 changed files with 324 additions and 86 deletions

View File

@@ -111,7 +111,7 @@ namespace Orchard.Tests.Modules.Indexing {
var thingType = new ContentTypeDefinitionBuilder()
.Named(ThingDriver.ContentTypeName)
.WithSetting("TypeIndexing.Included", "true")
.WithSetting("TypeIndexing.Indexes", "Search")
.Build();
_contentDefinitionManager
@@ -145,7 +145,7 @@ namespace Orchard.Tests.Modules.Indexing {
public void ShouldNotIndexContentIfIndexDocumentIsEmpty() {
var alphaType = new ContentTypeDefinitionBuilder()
.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();
_contentDefinitionManager

View File

@@ -6,4 +6,5 @@ Version: 1.6
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.
FeatureDescription: Lucene indexing services.
Dependencies: Orchard.Indexing
Category: Search

View File

@@ -2,9 +2,9 @@
using System.Linq;
using Orchard.Commands;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Indexing.Services;
using Orchard.Tasks.Indexing;
using Orchard.Utility.Extensions;
namespace Orchard.Indexing.Commands {
public class IndexingCommands : DefaultOrchardCommandHandler {
@@ -12,7 +12,6 @@ namespace Orchard.Indexing.Commands {
private readonly IIndexingService _indexingService;
private readonly IIndexingTaskManager _indexingTaskManager;
private readonly IContentManager _contentManager;
private const string SearchIndexName = "Search";
public IndexingCommands(
IIndexManager indexManager,
@@ -31,29 +30,66 @@ namespace Orchard.Indexing.Commands {
[OrchardSwitch]
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")]
[CommandHelp("index update\r\n\t" + "Updates the search index")]
public void Update() {
_indexingService.UpdateIndex(SearchIndexName);
[CommandHelp("index update <index>\r\n\t" + "Updates the specified index")]
public void Update(string index) {
if (string.IsNullOrWhiteSpace(index)) {
Context.Output.WriteLine(T("Invalid index name."));
return;
}
_indexingService.UpdateIndex(index);
Context.Output.WriteLine(T("Index is now being updated..."));
}
[CommandName("index rebuild")]
[CommandHelp("index rebuild \r\n\t" + "Rebuilds the search index")]
public void Rebuild() {
_indexingService.RebuildIndex(SearchIndexName);
[CommandHelp("index rebuild <index> \r\n\t" + "Rebuilds the specified index")]
public void Rebuild(string index) {
if (string.IsNullOrWhiteSpace(index)) {
Context.Output.WriteLine(T("Invalid index name."));
return;
}
_indexingService.RebuildIndex(index);
Context.Output.WriteLine(T("Index is now being rebuilt..."));
}
[CommandName("index search")]
[CommandHelp("index search /Query:<query>\r\n\t" + "Searches the specified <query> terms in the search index")]
[CommandName("index query")]
[CommandHelp("index query <index> /Query:<query>\r\n\t" + "Searches the specified <query> terms in the specified index")]
[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() ) {
Context.Output.WriteLine(T("No index available"));
return;
}
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(SearchIndexName);
var searchBuilder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(index);
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" : "");
@@ -76,15 +112,20 @@ namespace Orchard.Indexing.Commands {
}
[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")]
public void Stats() {
public void Stats(string index) {
if (string.IsNullOrWhiteSpace(index)) {
Context.Output.WriteLine(T("Invalid index name."));
return;
}
if ( !_indexManager.HasIndexProvider() ) {
Context.Output.WriteLine(T("No index available"));
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")]

View File

@@ -15,5 +15,8 @@ namespace Orchard.Indexing {
return 1;
}
// todo: When upgrading from 1, change TypeIndexing.Included to TypeIndexing.Indexes = "Search"
// todo: When upgrading from 1, define SearchSettingsPart.SelectedIndex to "Search"
}
}

View File

@@ -68,7 +68,7 @@ namespace Orchard.Indexing.Services
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) {

View File

@@ -166,6 +166,13 @@ namespace Orchard.Indexing.Services {
foreach (var item in contentItems) {
try {
// skip items from types which are not indexed
var settings = GetTypeIndexingSettings(item);
if (!settings.Indexes.Contains(indexName)) {
continue;
}
IDocumentIndex documentIndex = ExtractDocumentIndex(item);
if (documentIndex != null && documentIndex.IsDirty) {
@@ -195,8 +202,17 @@ namespace Orchard.Indexing.Services {
foreach (var item in indexingTasks) {
try {
IDocumentIndex documentIndex = null;
// 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) {
deleteFromIndex.Add(item.Id);
@@ -284,12 +300,6 @@ namespace Orchard.Indexing.Services {
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);
// call all handlers to add content to index
@@ -301,7 +311,7 @@ namespace Orchard.Indexing.Services {
if (contentItem == null ||
contentItem.TypeDefinition == null ||
contentItem.TypeDefinition.Settings == null) {
return new TypeIndexing {Included = false};
return new TypeIndexing {Indexes = ""};
}
return contentItem.TypeDefinition.Settings.GetModel<TypeIndexing>();
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
@@ -28,7 +29,7 @@ namespace Orchard.Indexing.Settings {
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
var model = new TypeIndexing();
updateModel.TryUpdateModel(model, "TypeIndexing", null, null);
builder.WithSetting("TypeIndexing.Included", model.Included ? true.ToString() : null);
builder.WithSetting("TypeIndexing.Indexes", model.Indexes);
CreateIndexingTasks();

View File

@@ -1,5 +1,12 @@
namespace Orchard.Indexing.Settings {
using System;
namespace Orchard.Indexing.Settings {
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); }
}
}
}

View File

@@ -61,7 +61,7 @@
}
} else
{
<div>@T("There are no indexes.")</div>
<div>@T("There is currently no index.")</div>
}
@if (Model.IndexProvider != null) {

View File

@@ -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>
@Html.ValidationMessageFor(m=>m.Included)
</fieldset>
}
@if (indexProvider != null) {
<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>
}

View File

@@ -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;
}
}
}
}

View File

@@ -36,15 +36,16 @@ namespace Orchard.Search.Controllers {
public Localizer T { get; set; }
public ActionResult Index(PagerParameters pagerParameters, string searchText = "") {
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
var searchFields = Services.WorkContext.CurrentSite.As<SearchSettingsPart>().SearchedFields;
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
var searchSettingsPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
try {
searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize,
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
searchFields,
searchSettingsPart.SearchIndex,
searchSettingsPart.SearchedFields,
searchHit => searchHit);
}
catch (Exception exception) {

View File

@@ -64,7 +64,8 @@ namespace Orchard.Search.Controllers {
return View("NoIndex");
}
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search");
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(settings.SearchIndex);
try {
builder.Parse(searchFields, searchText);

View File

@@ -46,14 +46,20 @@ namespace Orchard.Search.Controllers {
public ActionResult Index(PagerParameters pagerParameters, string q = "") {
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[] { });
try {
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().Record.FilterCulture,
searchFields,
searchSettingPart.SearchIndex,
searchSettingPart.SearchedFields,
searchHit => searchHit);
} catch(Exception exception) {
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);

View File

@@ -11,7 +11,6 @@ using Orchard.Search.ViewModels;
namespace Orchard.Search.Drivers {
public class SearchSettingsPartDriver : ContentPartDriver<SearchSettingsPart> {
private const string SearchIndexName = "Search";
private readonly IIndexManager _indexManager;
public SearchSettingsPartDriver(IIndexManager indexManager) {
@@ -30,24 +29,33 @@ namespace Orchard.Search.Drivers {
protected override DriverResult Editor(SearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape("Parts_Search_SiteSettings", () => {
SearchSettingsViewModel model = new SearchSettingsViewModel();
var model = new SearchSettingsViewModel();
String[] searchedFields = part.SearchedFields;
if (updater != null) {
// submitting: rebuild model from form data
if (updater.TryUpdateModel(model, Prefix, null, null)) {
// 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;
}
}
else if (_indexManager.HasIndexProvider()) {
// viewing editor: build model from part
model.FilterCulture = part.FilterCulture;
model.Entries = new List<SearchSettingsEntry>();
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(SearchIndexName)) {
model.Entries.Add(new SearchSettingsEntry { Field = field, Selected = searchedFields.Contains(field) });
model.SelectedIndex = part.SearchIndex;
model.Entries = _indexManager.GetSearchIndexProvider().List().Select(x => {
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);

View File

@@ -10,6 +10,7 @@ namespace Orchard.Search {
.ContentPartRecord()
.Column<bool>("FilterCulture")
.Column<string>("SearchedFields", c => c.Unlimited())
.Column<string>("SearchIndex")
);
ContentDefinitionManager.AlterTypeDefinition("SearchForm",
@@ -20,7 +21,15 @@ namespace Orchard.Search {
.WithSetting("Stereotype", "Widget")
);
return 1;
return 2;
}
public int UpdateFrom1() {
SchemaBuilder.AlterTable("SearchSettingsPartRecord", table => table
.AddColumn<string>("SearchIndex")
);
return 2;
}
}
}

View File

@@ -12,5 +12,10 @@ namespace Orchard.Search.Models {
get { return Record.FilterCulture; }
set { Record.FilterCulture = value; }
}
public string SearchIndex {
get { return Record.SearchIndex; }
set { Record.SearchIndex = value; }
}
}
}

View File

@@ -2,12 +2,13 @@ using Orchard.ContentManagement.Records;
namespace Orchard.Search.Models {
public class SearchSettingsPartRecord : ContentPartRecord {
public virtual bool FilterCulture { get; set; }
public virtual string SearchedFields { get; set; }
public SearchSettingsPartRecord() {
FilterCulture = false;
SearchedFields = "body, title";
}
public virtual bool FilterCulture { get; set; }
public virtual string SearchedFields { get; set; }
public virtual string SearchIndex { get; set; }
}
}

View File

@@ -47,6 +47,7 @@
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
@@ -56,6 +57,7 @@
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\SearchCommands.cs" />
<Compile Include="ContentPickerNavigationProvider.cs" />
<Compile Include="Controllers\ContentPickerController.cs" />
<Compile Include="ContentAdminMenu.cs" />
@@ -87,6 +89,9 @@
</ItemGroup>
<ItemGroup>
<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-search.css" />
<Content Include="Views\Web.config" />

View File

@@ -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>

View File

@@ -4,6 +4,6 @@ using Orchard.Indexing;
namespace Orchard.Search.Services {
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);
}
}

View File

@@ -21,18 +21,18 @@ namespace Orchard.Search.Services {
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
ISearchBuilder Search() {
ISearchBuilder Search(string index) {
return _indexManager.HasIndexProvider()
? _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search")
? _indexManager.GetSearchIndexProvider().CreateSearchBuilder(index)
: 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))
return new PageOfItems<T>(Enumerable.Empty<T>());
var searchBuilder = Search().Parse(searchFields, query);
var searchBuilder = Search(index).Parse(searchFields, query);
if (filterCulture) {
var culture = _cultureManager.GetSiteCulture();

View File

@@ -26,6 +26,7 @@ namespace Orchard.Search.Settings {
var model = new ContentPickerSearchFieldSettings();
if (updateModel.TryUpdateModel(model, "ContentPickerSearchFieldSettings", null, null)) {
builder.WithSetting("ContentPickerSearchFieldSettings.ShowSearchTab", model.ShowSearchTab.ToString(CultureInfo.InvariantCulture));
builder.WithSetting("ContentPickerSearchFieldSettings.SearchIndex", model.SearchIndex);
builder.WithSetting("ContentPickerSearchFieldSettings.DisplayedContentTypes", model.DisplayedContentTypes);
}

View File

@@ -5,6 +5,7 @@
}
public bool ShowSearchTab { get; set; }
public string SearchIndex { get; set; }
public string DisplayedContentTypes { get; set; }
}
}

View File

@@ -2,10 +2,16 @@
namespace Orchard.Search.ViewModels {
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 class IndexSettingsEntry {
public string Index { get; set; }
public IList<SearchSettingsEntry> Fields { get; set; }
}
public class SearchSettingsEntry {
public string Field { get; set; }
public bool Selected { get; set; }

View File

@@ -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>
<div>
@@ -7,6 +12,16 @@
</div>
</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>
<label for="@Html.FieldIdFor(m => m.DisplayedContentTypes)">@T("Content Types and Parts")</label>
@Html.TextBoxFor(m => m.DisplayedContentTypes)

View File

@@ -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>
<legend>@T("Search")</legend>
<div>
<label>@T("Searched fields")</label>
<span class="hint">@T("Check any property which should be used for search queries.")</span>
@{var entryIndex = 0;}
<label>@T("Indexes")</label>
@if (Model.Entries != null && Model.Entries.Any()) {
if (String.IsNullOrWhiteSpace(Model.SelectedIndex)) {
Model.Entries.Insert(0, new IndexSettingsEntry { Index = "" });
}
<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].Selected)
@Html.HiddenFor(m => m.Entries[entryIndex].Field)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndex].Selected)">@Model.Entries[entryIndex].Field</label>
@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>
entryIndex = entryIndex + 1;
fieldIndex++;
}
</ul>
}
</li>
entryIndex++;
}
</ul>
<span class="hint">@T("Check any property which should be used for search queries.")</span>
}
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>
@@ -33,3 +60,20 @@
</div>
</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>
}

View File

@@ -19,12 +19,12 @@
<Metadata>
<Types>
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
<TagsPart />
<LocalizationPart />
<AutoroutePart />
</Page>
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
<CommentsPart />
<TagsPart />
<LocalizationPart />

View File

@@ -18,13 +18,13 @@
<Metadata>
<Types>
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
<Page ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
<TagsPart />
<LocalizationPart />
<TitlePart/>
<AutoroutePart />
</Page>
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Included="true">
<BlogPost ContentTypeSettings.Draftable="True" TypeIndexing.Indexes="Search">
<CommentsPart />
<TagsPart />
<LocalizationPart />

View File

@@ -13,11 +13,11 @@ namespace Orchard.Indexing {
#region IIndexManager Members
public bool HasIndexProvider() {
return _indexProviders.AsQueryable().Count() > 0;
return _indexProviders.Any();
}
public IIndexProvider GetSearchIndexProvider() {
return _indexProviders.AsQueryable().FirstOrDefault();
return _indexProviders.FirstOrDefault();
}
#endregion

View File

@@ -2,8 +2,8 @@
namespace Orchard.Indexing {
public static class MetaDataExtensions {
public static ContentTypeDefinitionBuilder Indexed(this ContentTypeDefinitionBuilder builder) {
return builder.WithSetting("TypeIndexing.Included", "true");
public static ContentTypeDefinitionBuilder Indexed(this ContentTypeDefinitionBuilder builder, params string[] indexes) {
return builder.WithSetting("TypeIndexing.Indexes", string.Join(",", indexes ?? new string[0]));
}
}
}