使用 GlassMapper 的 Sitecore Lucene 搜索不工作
Sitecore Lucene Search With GlassMapper not working
过去几周我一直在努力自学 Sitecore。
目前我正在尝试创建一个食谱列表供用户搜索。
然而,每个食谱都包含成分,Lucene 将这些成分作为包含项目 ID 的字符串返回。我想在我的代码中有一个成分列表,所以我试了一下 GlassMapper。
所以我通过更改名称从 Lucene 中排除了代码中的成分列表,这样 Lucene 就找不到该字段了。
然后我设置 GlassMapper 来填充成分列表。但是,该列表保持为空。
如何让 GlassMapper 为我填充此列表?
我的代码:
食谱 class
[SitecoreType(TemplateId= "{1CF86642-6EC5-4B26-B8A7-1B2EC41F7783}")]
public class Recipe : SearchResultItem
{
[SitecoreId]
public Guid Id { get { return base.ItemId.Guid; } }
public virtual string RecipeName { get; set; }
public virtual string BookName { get; set; }
public virtual IEnumerable<Ingredient> _Ingredients { get; set; }
public virtual int AmountOfPeople { get; set; }
}
成分 class
[SitecoreType(TemplateId = "{730A0D54-A697-4DAA-908A-279CD24A9F41}")]
public class Ingredient : SearchResultItem
{
[SitecoreId]
Guid Id { get; }
[IndexField("Name")]
public virtual string IngredientName { get; set; }
}
GlassMapperScCustom class (我只编辑了这个方法)
public static IConfigurationLoader[] GlassLoaders()
{
var attributes = new SitecoreAttributeConfigurationLoader("Receptenboek");
var loader = new SitecoreFluentConfigurationLoader();
var config = loader.Add<Recipe>();
config.Id(x => x.ItemId);
config.Info(x => x.Language).InfoType(SitecoreInfoType.Language);
config.Info(x => x.Version).InfoType(SitecoreInfoType.Version);
config.Field(x => x._Ingredients);
config.Info(x => x.Uri).InfoType(SitecoreInfoType.Url);
return new IConfigurationLoader[] {attributes, loader };
}
配方控制器
[HttpGet]
public ActionResult Index()
{
List<Recipe> recipes;
IQueryable<Recipe> query;
string index = string.Format("sitecore_{0}_index", Sitecore.Context.Database.Name);
var sitecoreService = new SitecoreService(Sitecore.Context.Database.Name);
string search = WebUtil.GetQueryString("search");
using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
if (!string.IsNullOrEmpty(search))
{
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").Where(p => p.RecipeName.Contains(search));
}
else
{
search = "";
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe");
}
recipes = query.ToList();
foreach( var r in recipes)
{
sitecoreService.Map(r);
Sitecore.Diagnostics.Log.Audit("SWELF" + r.RecipeName + "- " + r.BookName + " - " + r.AmountOfPeople + " - " + r.Name + "--" + r._Ingredients.Count(), this);
}
}
RecipesViewModel bvm = new RecipesViewModel() { Recipes = recipes, Search = search };
return View(bvm);
}
玩了一会儿之后,我决定将搜索和映射分开一些。我将 Recipe 模型与 Lucene 一起使用,并创建了一个 ViewModel 以使用 GlassMapper 将字段映射到。
食谱class没有改变。
成分 class 没有改变。
不需要 GlassMapperScCustom class,所以我恢复了它的默认值。
RecipeViewModel class
映射到此 class 后,成分列表具有正确数量的成分,但其所有字段均为空。
在互联网上多看了一会儿之后,我发现了这个 Whosebug post:
我决定试试 SitecoreFieldType,结果成功了!
[SitecoreType(TemplateId = "{1CF86642-6EC5-4B26-B8A7-1B2EC41F7783}", AutoMap = true)]
public class RecipeViewModel : BaseFields
{
[SitecoreId]
public ID Id { get; set; }
public virtual string RecipeName { get; set; }
public virtual string BookName { get; set; }
[SitecoreField(FieldId = "{D1603482-7CBC-4E55-9CCB-E51DC0FC5A0B}", FieldType = SitecoreFieldType.Multilist)]
public virtual IEnumerable<IngredientViewModel> Ingredients { get; set; }
public virtual int AmountOfPeople { get; set; }
}
配方控制器
原来是映射错误的方式。我找到了一个使用 SitecoreService.GetItem<>()
将列表映射到另一个列表的示例
[HttpGet]
public ActionResult Index()
{
List<RecipeViewModel> recipes;
List<Recipe> query;
string index = string.Format("sitecore_{0}_index", Sitecore.Context.Database.Name);
var sitecoreService = new SitecoreService(Sitecore.Context.Database.Name);
string search = WebUtil.GetQueryString("search");
//Search with Lucene
using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
if (!string.IsNullOrEmpty(search))
{
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").Where(p => p.RecipeName.Contains(search)).ToList();
}
else
{
search = "";
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").ToList();
}
}
//Map to ViewModel
recipes = query.Select(x => sitecoreService.GetItem<RecipeViewModel>(x.ItemId.Guid)).ToList();
RecipesViewModel bvm = new RecipesViewModel() { Recipes = recipes, Search = search };
return View(bvm);
}
还有一个问题
因为我的 ViewModel 没有从 SearchResultItem 继承很多有用的字段,这些字段在映射中丢失了。为了从 SearchResultItem 中保留我需要的字段,我创建了一个 BaseFields class 供我的 ViewModel 继承。我现在只需要 Url,但这可以很容易地扩展到更多字段。
public class BaseFields
{
public virtual string Url { get; set; }
}
过去几周我一直在努力自学 Sitecore。
目前我正在尝试创建一个食谱列表供用户搜索。
然而,每个食谱都包含成分,Lucene 将这些成分作为包含项目 ID 的字符串返回。我想在我的代码中有一个成分列表,所以我试了一下 GlassMapper。
所以我通过更改名称从 Lucene 中排除了代码中的成分列表,这样 Lucene 就找不到该字段了。 然后我设置 GlassMapper 来填充成分列表。但是,该列表保持为空。
如何让 GlassMapper 为我填充此列表?
我的代码:
食谱 class
[SitecoreType(TemplateId= "{1CF86642-6EC5-4B26-B8A7-1B2EC41F7783}")]
public class Recipe : SearchResultItem
{
[SitecoreId]
public Guid Id { get { return base.ItemId.Guid; } }
public virtual string RecipeName { get; set; }
public virtual string BookName { get; set; }
public virtual IEnumerable<Ingredient> _Ingredients { get; set; }
public virtual int AmountOfPeople { get; set; }
}
成分 class
[SitecoreType(TemplateId = "{730A0D54-A697-4DAA-908A-279CD24A9F41}")]
public class Ingredient : SearchResultItem
{
[SitecoreId]
Guid Id { get; }
[IndexField("Name")]
public virtual string IngredientName { get; set; }
}
GlassMapperScCustom class (我只编辑了这个方法)
public static IConfigurationLoader[] GlassLoaders()
{
var attributes = new SitecoreAttributeConfigurationLoader("Receptenboek");
var loader = new SitecoreFluentConfigurationLoader();
var config = loader.Add<Recipe>();
config.Id(x => x.ItemId);
config.Info(x => x.Language).InfoType(SitecoreInfoType.Language);
config.Info(x => x.Version).InfoType(SitecoreInfoType.Version);
config.Field(x => x._Ingredients);
config.Info(x => x.Uri).InfoType(SitecoreInfoType.Url);
return new IConfigurationLoader[] {attributes, loader };
}
配方控制器
[HttpGet]
public ActionResult Index()
{
List<Recipe> recipes;
IQueryable<Recipe> query;
string index = string.Format("sitecore_{0}_index", Sitecore.Context.Database.Name);
var sitecoreService = new SitecoreService(Sitecore.Context.Database.Name);
string search = WebUtil.GetQueryString("search");
using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
if (!string.IsNullOrEmpty(search))
{
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").Where(p => p.RecipeName.Contains(search));
}
else
{
search = "";
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe");
}
recipes = query.ToList();
foreach( var r in recipes)
{
sitecoreService.Map(r);
Sitecore.Diagnostics.Log.Audit("SWELF" + r.RecipeName + "- " + r.BookName + " - " + r.AmountOfPeople + " - " + r.Name + "--" + r._Ingredients.Count(), this);
}
}
RecipesViewModel bvm = new RecipesViewModel() { Recipes = recipes, Search = search };
return View(bvm);
}
玩了一会儿之后,我决定将搜索和映射分开一些。我将 Recipe 模型与 Lucene 一起使用,并创建了一个 ViewModel 以使用 GlassMapper 将字段映射到。
食谱class没有改变。
成分 class 没有改变。
不需要 GlassMapperScCustom class,所以我恢复了它的默认值。
RecipeViewModel class
映射到此 class 后,成分列表具有正确数量的成分,但其所有字段均为空。
在互联网上多看了一会儿之后,我发现了这个 Whosebug post:
我决定试试 SitecoreFieldType,结果成功了!
[SitecoreType(TemplateId = "{1CF86642-6EC5-4B26-B8A7-1B2EC41F7783}", AutoMap = true)]
public class RecipeViewModel : BaseFields
{
[SitecoreId]
public ID Id { get; set; }
public virtual string RecipeName { get; set; }
public virtual string BookName { get; set; }
[SitecoreField(FieldId = "{D1603482-7CBC-4E55-9CCB-E51DC0FC5A0B}", FieldType = SitecoreFieldType.Multilist)]
public virtual IEnumerable<IngredientViewModel> Ingredients { get; set; }
public virtual int AmountOfPeople { get; set; }
}
配方控制器
原来是映射错误的方式。我找到了一个使用 SitecoreService.GetItem<>()
[HttpGet]
public ActionResult Index()
{
List<RecipeViewModel> recipes;
List<Recipe> query;
string index = string.Format("sitecore_{0}_index", Sitecore.Context.Database.Name);
var sitecoreService = new SitecoreService(Sitecore.Context.Database.Name);
string search = WebUtil.GetQueryString("search");
//Search with Lucene
using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
{
if (!string.IsNullOrEmpty(search))
{
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").Where(p => p.RecipeName.Contains(search)).ToList();
}
else
{
search = "";
query = context.GetQueryable<Recipe>().Where(p => p.Path.Contains("/sitecore/Content/Home/Recipes/")).Where(p => p.TemplateName == "Recipe").ToList();
}
}
//Map to ViewModel
recipes = query.Select(x => sitecoreService.GetItem<RecipeViewModel>(x.ItemId.Guid)).ToList();
RecipesViewModel bvm = new RecipesViewModel() { Recipes = recipes, Search = search };
return View(bvm);
}
还有一个问题
因为我的 ViewModel 没有从 SearchResultItem 继承很多有用的字段,这些字段在映射中丢失了。为了从 SearchResultItem 中保留我需要的字段,我创建了一个 BaseFields class 供我的 ViewModel 继承。我现在只需要 Url,但这可以很容易地扩展到更多字段。
public class BaseFields
{
public virtual string Url { get; set; }
}