我刚刚将Lucene搜索包含在我的第一个应用程序(ASP.NET MVC 5)中,但我最初在索引数据库时遇到了一些问题,并确定了正确的整体应用程序架构应该是什么。
我目前的设置是:
Azure调度程序调用我的Web API来请求索引所有类别,然后单独调用所有项目。另一个每3个月运行一次的调度程序调用Optimize(db不会经常更改)。 API从数据库中获取所有实体,并将新的CloudQueueMessage添加到CloudQueueClient。
正在运行的WebJob从队列中拉出并使用ID回调到我的Web API。 API使用AzureDirectory项目(https://azuredirectory.codeplex.com/)抓取项目并相应地从Lucene索引中添加或删除它。这一切都按预期运行,如果我手动将ID发布到我的API方法,一切都很棒。当它通过WebJob运行时,我的索引以某种方式变得腐败,任何调用,甚至获取索引项的数量,返回404未找到寻找我目录中不存在的文件(通常类似于_1a.cfs)
我认为这是某种锁定问题,或者我的物品没有被妥善处理,但我看不出我出错的地方,我不确定这是最好的方法构建应用程序和工作流程。下面粘贴了一半代码,任何帮助都会非常感激!
WebJob:
public class Program
{
static void Main()
{
JobHost host = new JobHost();
host.RunAndBlock();
}
public static void IndexItemOrCategory([QueueTrigger("searchindexrequest")] string id)
{
string baseUri = ConfigurationSettings.AppSettings["BaseUri"];
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
string response = client.GetStringAsync("api/search/indexitem/" + id).Result;
Console.Out.WriteLine(response);
}
}
}
API:
public HttpResponseMessage IndexItem(string id)
{
try
{
var item = db.Items.Find(dbId);
if (item != null && item.Active && !string.IsNullOrWhiteSpace(item.Name))
LuceneSearch.AddUpdateLuceneIndex(item);
else
{
LuceneSearch.RemoveLuceneIndexRecord<Item>(dbId);
removed = true;
}
}
catch (Exception exc)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exc);
}
return Request.CreateResponse(HttpStatusCode.OK, id + (removed ? " removed " : " indexed ") + "successfully.");
}
public class LuceneSearch
{
private static CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureConnection"].ToString());
private static AzureDirectory azureDirectory = new AzureDirectory(storageAccount, "lucene-search", new RAMDirectory());
public static void AddUpdateLuceneIndex(Item item)
{
AddToLuceneIndex(item);
}
private static void AddToLuceneIndex(Item toIndex)
{
using (StandardAnalyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30))
{
using (IndexWriter writer = new IndexWriter(azureDirectory, analyzer, new IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH)))
{
string Id = "Item" + toIndex.ItemID.ToString();
//Remove any existing index entry
var searchQuery = new TermQuery(new Term("Id", Id));
writer.DeleteDocuments(searchQuery);
string name = string.IsNullOrWhiteSpace(toIndex.CommonName) ? toIndex.Name : toIndex.Name + ", " + toIndex.CommonName;
if (!string.IsNullOrWhiteSpace(name))
{
//Create new entry
Document doc = new Document();
doc.Add(new Field("Id", Id, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("Name", toIndex.Name, Field.Store.YES, Field.Index.ANALYZED));
if (!string.IsNullOrWhiteSpace(toIndex.Description1))
doc.Add(new Field("Description", toIndex.Description1, Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("CategoryName", toIndex.Category.Name, Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("SeoUrl", toIndex.SeoUrl, Field.Store.YES, Field.Index.NOT_ANALYZED));
if (!string.IsNullOrWhiteSpace(toIndex.Image1))
doc.Add(new Field("Image", toIndex.Image1, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("CategorySeoUrl", toIndex.Category.SeoUrl, Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.AddDocument(doc);
}
writer.Dispose();
}
}
}
...
}