Fix small bug in index provider

Also cleanup the API a bit
Also provide more detailled statistics about the search index on the
"Search Index Management" page.

--HG--
branch : dev
This commit is contained in:
Renaud Paquay 2010-07-11 12:11:38 -07:00
parent 2761c3520b
commit 5a7724e2e1
9 changed files with 65 additions and 37 deletions

View File

@ -278,7 +278,7 @@ namespace Orchard.Tests.Modules.Indexing {
_provider.Store("default", _provider.New(2).Add("b", DateTime.Now).Store()); _provider.Store("default", _provider.New(2).Add("b", DateTime.Now).Store());
_provider.Store("default", _provider.New(3).Add("c", 333)); _provider.Store("default", _provider.New(3).Add("c", 333));
Assert.That(_provider.GetFields("default").Length, Is.EqualTo(4)); Assert.That(_provider.GetFields("default").Count(), Is.EqualTo(4));
Assert.That(_provider.GetFields("default").OrderBy(s => s).ToArray(), Is.EqualTo(new [] { "a", "b", "c", "id"})); Assert.That(_provider.GetFields("default").OrderBy(s => s).ToArray(), Is.EqualTo(new [] { "a", "b", "c", "id"}));
} }

View File

@ -210,12 +210,13 @@ namespace Lucene.Services {
return _appDataFolder.MapPath(_appDataFolder.Combine(_basePath, indexName + ".settings.xml")); return _appDataFolder.MapPath(_appDataFolder.Combine(_basePath, indexName + ".settings.xml"));
} }
public DateTime GetLastIndexUtc(string indexName) { public DateTime? GetLastIndexUtc(string indexName) {
var settingsFileName = GetSettingsFileName(indexName); var settingsFileName = GetSettingsFileName(indexName);
return File.Exists(settingsFileName) if (!File.Exists(settingsFileName))
? DateTime.Parse(XDocument.Load(settingsFileName).Descendants(LastIndexUtc).First().Value) return null;
: DefaultMinDateTime;
return DateTime.Parse(XDocument.Load(settingsFileName).Descendants(LastIndexUtc).First().Value);
} }
public void SetLastIndexUtc(string indexName, DateTime lastIndexUtc) { public void SetLastIndexUtc(string indexName, DateTime lastIndexUtc) {
@ -239,15 +240,15 @@ namespace Lucene.Services {
doc.Save(settingsFileName); doc.Save(settingsFileName);
} }
public string[] GetFields(string indexName) { public IEnumerable<string> GetFields(string indexName) {
if ( !Exists(indexName) ) { if ( !Exists(indexName) ) {
return new string[0]; return Enumerable.Empty<string>();
} }
var reader = IndexReader.Open(GetDirectory(indexName), true); var reader = IndexReader.Open(GetDirectory(indexName), true);
try { try {
return reader.GetFieldNames(IndexReader.FieldOption.ALL).ToArray(); return reader.GetFieldNames(IndexReader.FieldOption.ALL).ToList();
} }
finally { finally {
reader.Close(); reader.Close();

View File

@ -18,9 +18,9 @@ namespace Orchard.Indexing.Controllers {
public Localizer T { get; set; } public Localizer T { get; set; }
public ActionResult Index() { public ActionResult Index() {
var viewModel = new IndexViewModel {HasIndexToManage = _indexingService.HasIndexToManage, IndexUpdatedUtc = _indexingService.GetIndexUpdatedUtc()}; var viewModel = new IndexViewModel { IndexEntry = _indexingService.GetIndexEntry() };
if (!viewModel.HasIndexToManage) if (viewModel.IndexEntry == null)
Services.Notifier.Information(T("There is no search index to manage for this site.")); Services.Notifier.Information(T("There is no search index to manage for this site."));
return View(viewModel); return View(viewModel);
@ -28,7 +28,7 @@ namespace Orchard.Indexing.Controllers {
[HttpPost] [HttpPost]
public ActionResult Update() { public ActionResult Update() {
if ( !Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")) ) if (!Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
_indexingService.UpdateIndex(); _indexingService.UpdateIndex();
@ -38,7 +38,7 @@ namespace Orchard.Indexing.Controllers {
[HttpPost] [HttpPost]
public ActionResult Rebuild() { public ActionResult Rebuild() {
if ( !Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")) ) if (!Services.Authorizer.Authorize(Permissions.ManageSearchIndex, T("Not allowed to manage the search index.")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
_indexingService.RebuildIndex(); _indexingService.RebuildIndex();

View File

@ -1,10 +1,17 @@
using System; using System;
using System.Collections.Generic;
namespace Orchard.Indexing.Services { namespace Orchard.Indexing.Services {
public class IndexEntry {
public string IndexName { get; set; }
public int DocumentCount { get; set; }
public DateTime? LastUpdateUtc { get; set; }
public IEnumerable<string> Fields { get; set; }
}
public interface IIndexingService : IDependency { public interface IIndexingService : IDependency {
bool HasIndexToManage { get; }
void RebuildIndex(); void RebuildIndex();
void UpdateIndex(); void UpdateIndex();
DateTime GetIndexUpdatedUtc(); IndexEntry GetIndexEntry();
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Localization.Services; using Orchard.Localization.Services;
using Orchard.UI.Notify; using Orchard.UI.Notify;
@ -22,10 +21,6 @@ namespace Orchard.Indexing.Services
public IOrchardServices Services { get; set; } public IOrchardServices Services { get; set; }
public Localizer T { get; set; } public Localizer T { get; set; }
public bool HasIndexToManage {
get { return _indexManager.HasIndexProvider(); }
}
void IIndexingService.RebuildIndex() { void IIndexingService.RebuildIndex() {
if (!_indexManager.HasIndexProvider()) { if (!_indexManager.HasIndexProvider()) {
Services.Notifier.Warning(T("There is no search index to rebuild.")); Services.Notifier.Warning(T("There is no search index to rebuild."));
@ -50,10 +45,17 @@ namespace Orchard.Indexing.Services
Services.Notifier.Information(T("The search index has been updated.")); Services.Notifier.Information(T("The search index has been updated."));
} }
DateTime IIndexingService.GetIndexUpdatedUtc() { IndexEntry IIndexingService.GetIndexEntry() {
return !HasIndexToManage var provider = _indexManager.GetSearchIndexProvider();
? DateTime.MinValue if (provider == null)
: _indexManager.GetSearchIndexProvider().GetLastIndexUtc(SearchIndexName); return null;
return new IndexEntry {
IndexName = SearchIndexName,
DocumentCount = provider.NumDocs(SearchIndexName),
Fields = provider.GetFields(SearchIndexName),
LastUpdateUtc = provider.GetLastIndexUtc(SearchIndexName)
};
} }
} }
} }

View File

@ -59,14 +59,14 @@ namespace Orchard.Indexing.Services {
_indexProvider = _indexManager.GetSearchIndexProvider(); _indexProvider = _indexManager.GetSearchIndexProvider();
var updateIndexDocuments = new List<IDocumentIndex>(); var updateIndexDocuments = new List<IDocumentIndex>();
DateTime lastIndexing; DateTime? lastIndexUtc;
// Do we need to rebuild the full index (first time module is used, or rebuild index requested) ? // Do we need to rebuild the full index (first time module is used, or rebuild index requested) ?
if (_indexProvider.IsEmpty(SearchIndexName)) { if (_indexProvider.IsEmpty(SearchIndexName)) {
Logger.Information("Rebuild index started"); Logger.Information("Rebuild index started");
// mark current last task, as we should process older ones (in case of rebuild index only) // mark current last task, as we should process older ones (in case of rebuild index only)
lastIndexing = _indexingTaskManager.GetLastTaskDateTime(); lastIndexUtc = _indexingTaskManager.GetLastTaskDateTime();
// get every existing content item to index it // get every existing content item to index it
foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) { foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) {
@ -91,15 +91,15 @@ namespace Orchard.Indexing.Services {
} }
else { else {
// retrieve last processed index time // retrieve last processed index time
lastIndexing = _indexProvider.GetLastIndexUtc(SearchIndexName); lastIndexUtc = _indexProvider.GetLastIndexUtc(SearchIndexName);
} }
_indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow); _indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow);
// retrieve not yet processed tasks // retrieve not yet processed tasks
var taskRecords = lastIndexing == DateTime.MinValue var taskRecords = lastIndexUtc == null
? _repository.Fetch(x => true).ToArray() ? _repository.Fetch(x => true).ToArray()
: _repository.Fetch(x => x.CreatedUtc > lastIndexing).ToArray(); : _repository.Fetch(x => x.CreatedUtc > lastIndexUtc).ToArray();
// nothing to do ? // nothing to do ?

View File

@ -1,10 +1,8 @@
using System; using Orchard.Indexing.Services;
using Orchard.Mvc.ViewModels; using Orchard.Mvc.ViewModels;
namespace Orchard.Indexing.ViewModels { namespace Orchard.Indexing.ViewModels {
public class IndexViewModel : BaseViewModel { public class IndexViewModel : BaseViewModel {
public bool HasIndexToManage { get; set; } public IndexEntry IndexEntry { get; set;}
//todo: hang the index updated date off here to show in the admin UI (e.g. -> index updated: June 4, 2010 [update index])
public DateTime IndexUpdatedUtc { get; set; }
} }
} }

View File

@ -4,13 +4,33 @@ Html.RegisterStyle("admin.css"); %>
<h1><%:Html.TitleForPage(T("Search Index Management").ToString()) %></h1><% <h1><%:Html.TitleForPage(T("Search Index Management").ToString()) %></h1><%
using (Html.BeginForm("update", "admin", FormMethod.Post, new {area = "Orchard.Indexing"})) { %> using (Html.BeginForm("update", "admin", FormMethod.Post, new {area = "Orchard.Indexing"})) { %>
<fieldset> <fieldset>
<p><%:T("The search index was last updated {0}.", Html.DateTimeRelative(Model.IndexUpdatedUtc, T))%> <button type="submit" title="<%:T("Update the search index.") %>" class="primaryAction"><%:T("Update")%></button></p> <% if (Model.IndexEntry == null) {%>
<p><%:T("There is currently no search index")%></p>
<% } else if (Model.IndexEntry.LastUpdateUtc == null) { %>
<p><%:T("The search index has not been built yet.")%></p>
<% } else { %>
<% if (Model.IndexEntry.DocumentCount == 0) { %>
<p><%:T("The search index does not contain any document.")%></p>
<% } else { %>
<p><%:T("The search index contains {0} document(s).", Model.IndexEntry.DocumentCount)%></p>
<% } %>
<% if (!Model.IndexEntry.Fields.Any()) { %>
<p><%:T("The search index does not contain any field.")%></p>
<% } else { %>
<p><%:T("The search index contains the following fields: {0}.", string.Join(T(", ").Text, Model.IndexEntry.Fields))%></p>
<% } %>
<p><%:T("The search index was last updated {0}.", Html.DateTimeRelative(Model.IndexEntry.LastUpdateUtc.Value, T))%></p>
<% } %>
<p><%:T("Update the search index now: ") %><button type="submit" title="<%:T("Update the search index.") %>" class="primaryAction"><%:T("Update")%></button></p>
<%:Html.AntiForgeryTokenOrchard() %> <%:Html.AntiForgeryTokenOrchard() %>
</fieldset><% </fieldset><%
} }
using (Html.BeginForm("rebuild", "admin", FormMethod.Post, new {area = "Orchard.Search"})) { %> using (Html.BeginForm("rebuild", "admin", FormMethod.Post, new {area = "Orchard.Search"})) { %>
<fieldset> <fieldset>
<p><%:T("Rebuild the search index for a fresh start.") %> <button type="submit" title="<%:T("Rebuild the search index.") %>"><%:T("Rebuild") %></button></p> <p><%:T("Rebuild the search index for a fresh start.") %>
<button type="submit" title="<%:T("Rebuild the search index.") %>"><%:T("Rebuild") %></button></p>
<%:Html.AntiForgeryTokenOrchard() %> <%:Html.AntiForgeryTokenOrchard() %>
</fieldset><% </fieldset><%
} %> } %>

View File

@ -64,7 +64,7 @@ namespace Orchard.Indexing {
/// <summary> /// <summary>
/// Returns the date and time when the index was last processed /// Returns the date and time when the index was last processed
/// </summary> /// </summary>
DateTime GetLastIndexUtc(string indexName); DateTime? GetLastIndexUtc(string indexName);
/// <summary> /// <summary>
/// Sets the date and time when the index was last processed /// Sets the date and time when the index was last processed
@ -74,6 +74,6 @@ namespace Orchard.Indexing {
/// <summary> /// <summary>
/// Returns every field available in the specified index /// Returns every field available in the specified index
/// </summary> /// </summary>
string[] GetFields(string indexName); IEnumerable<string> GetFields(string indexName);
} }
} }