我在一个索引中有2个类型,并且都有Suggest字段(根据需要)
public class LegalAreaSearchModel : LegalAreaModel
{
public SuggestField Suggest
{
get
{
List<string> input = new List<string>();
string[] childArea = !string.IsNullOrEmpty(this.LegalArea) ? this.LegalArea.Split(' ') : new string[] { "" };
string[] ParentArea = !string.IsNullOrEmpty(this.Parent) ? this.Parent.Split(' ') : new string[] { "" };
input.AddRange(childArea);
input.AddRange(ParentArea);
return
new SuggestField
{
Input = input,
Output = this.LegalArea,
Payload = new
{
Id = this.RowId,
Name = !string.IsNullOrEmpty(this.Parent) ? this.Parent + "/" + this.LegalArea : this.LegalArea,
Type = "Specialization"
},
Weight = !string.IsNullOrEmpty(this.LegalArea) ? this.LegalArea.Length : 0
};
}
}
}
AND
public class LegalDocumentSearchModel : LegalDocumentModel
{
public LegalDocumentSearchModel()
{
//this = ObjectCopier.Clone<LegalDocumentSearchModel>(legalDocumentSearchModel);
SupplierDetails = new List<LegalDocumentSupplierDetailForSearch>();
CategoryDetails = new List<CategoryDetails>();
}
[Nested()]
public List<LegalDocumentSupplierDetailForSearch> SupplierDetails { get; set; }
[Nested()]
public List<CategoryDetails> CategoryDetails { get; set; }
public SuggestField Suggest
{
get
{
return
new SuggestField
{
Input = new List<string>(!string.IsNullOrEmpty(this.Name) ? this.Name.Split(' ') : new string[] { "" }) { this.Name },
Output = this.Name,
Payload = new
{
Id = this.RowId,
SEOFriendlyURLName = !string.IsNullOrEmpty(this.SEOFriendlyURLName) ? string.Concat(this.SEOFriendlyURLName) : string.Empty,
Name = this.Name,
ProductType = this.ProductType,
Description = this.Description
},
Weight = !string.IsNullOrEmpty(this.Description) ? this.Description.Length : 0
};
}
}
}
public class LegalDocumentSupplierDetailForSearch
{
public string PinCode { get; set; }
public string Lattitude { get; set; }
public string Longitude { get; set; }
}
public class CategoryDetails
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
现在我的搜索如下
List<AdvocateListingSuggestionModel> lsResult = new List<AdvocateListingSuggestionModel>();
var result = _searchProvider.Client.Suggest<LegalAreaSearchModel>(s => s
.Index(SearchConfigurationManager.DefaultSearchIndex)
.Completion("ml-la-suggestions", c => c
.Text(Search)
.Field(p => p.Suggest)
.Fuzzy(fz => fz
.Fuzziness(Fuzziness.Auto))
)
);
我也从其他类型获得结果(混合)我们如何限制只有一种类型的结果
Type1.LegalAreaSearchModel 键入2.LegalDocumentSearchModel
我的索引创建如下
public static bool CheckForIndex(ElasticSearchProvider searchProvider)
{
Nest.IndexExistsRequest idr = new Nest.IndexExistsRequest(Nest.Indices.Index(new Nest.IndexName() { Name = SearchConfigurationManager.DefaultSearchIndex }));
var indxres = searchProvider.Client.IndexExists(idr);
if (!indxres.Exists)
{
searchProvider.Client.CreateIndex(SearchConfigurationManager.DefaultSearchIndex, i => i
.Settings(s => s
.NumberOfShards(2)
.NumberOfReplicas(0)
.Analysis(analysis => analysis
.Tokenizers(tokenizers => tokenizers
.Pattern("ml-id-tokenizer", p => p.Pattern(@"\W+"))
)
.TokenFilters(tokenfilters => tokenfilters
.WordDelimiter("ml-id-words", wd => wd
.SplitOnCaseChange()
.PreserveOriginal()
.SplitOnNumerics()
.GenerateNumberParts(false)
.GenerateWordParts()
)
)
.Analyzers(analyzers => analyzers
.Custom("ml-id-analyzer", c => c
.Tokenizer("ml-id-tokenizer")
.Filters("ml-id-words", "lowercase")
)
.Custom("ml-id-keyword", c => c
.Tokenizer("keyword")
.Filters("lowercase")
)
)
)
));
}
return true;
}
创建文档类型如下
public bool CreateDocumentIndex()
{
bool retVal = false;
if (Common.CheckForIndex(_searchProvider))
{
var res = _searchProvider.Client.Map<LegalDocumentSearchModel>(m =>
m.Index(SearchConfigurationManager.DefaultSearchIndex)
.Type(this.type)
.AutoMap()
.Properties(ps => ps
.String(s => s
.Name(p => p.Id)
.Analyzer("ml-id-analyzer")
.Fields(f => f
.String(p => p.Name("keyword").Analyzer("ml-id-keyword"))
.String(p => p.Name("raw").Index(FieldIndexOption.NotAnalyzed))
)
)
.Completion(c => c
.Name(p => p.Suggest)
.Payloads()
)
));
retVal = res.IsValid;
}
return retVal;
}
创建LegalArea类型如下
public bool CreateLegalAreaIndex()
{
bool retVal = false;
if (Common.CheckForIndex(_searchProvider))
{
var res = _searchProvider.Client.Map<LegalAreaSearchModel>(m =>
m.Index(SearchConfigurationManager.DefaultSearchIndex)
.Type(this.type)
.AutoMap()
.Properties(ps => ps
.String(s => s
.Name(p => p.Id)
.Analyzer("ml-id-analyzer")
.Fields(f => f
.String(p => p.Name("keyword").Analyzer("ml-id-keyword"))
.String(p => p.Name("raw").Index(FieldIndexOption.NotAnalyzed))
)
)
.Completion(c => c
.Name(p => p.Suggest)
.Payloads()
)
));
retVal = res.IsValid;
}
return retVal;
}
现在,当我按照以下方式运行法律区域建议时
public List<AdvocateListingSuggestionModel> LegalAreaSuggestion(string Search)
{
List<AdvocateListingSuggestionModel> lsResult = new List<AdvocateListingSuggestionModel>();
var result = _searchProvider.Client.Suggest<LegalAreaSearchModel>(s => s
.Index(SearchConfigurationManager.DefaultSearchIndex)
.Completion("ml-la-suggestions", c => c
.Text(Search)
.Field(p => p.Suggest)
.Fuzzy(fz => fz
.Fuzziness(Fuzziness.Auto))
)
);
if (result.IsValid)
{
lsResult = result.Suggestions["ml-la-suggestions"]
.FirstOrDefault()
.Options
.Select(suggest => suggest.Payload<AdvocateListingSuggestionModel>()).ToList();
}
return lsResult;
}
我也收到了LegalDocumentSearchModel的结果。请建议
由于
答案 0 :(得分:0)
建议者在索引级别工作,即one Finite State Transducer (FST) is created for a field per index,因此如果您在同一索引中有两个具有相同字段名称的类型(两个字段必须属于同一类型) ,两种类型都将在一个FST中表示数据。
我们可以通过一个简单的例子看到这一点。这里我们有两种类型的完成字段,我们将索引到同一索引
public class Band
{
public int Id { get; set;}
public CompletionField<object> Suggest { get; set;}
}
public class Sport
{
public int Id { get; set;}
public CompletionField<object> Suggest { get; set; }
}
void Main()
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(connectionSettings);
// just so we can re-run this example...
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
client.CreateIndex(defaultIndex, ci => ci
.Mappings(m => m
.Map<Band>(l => l
.AutoMap()
.Properties(p => p
.Completion(c => c
.Name(n => n.Suggest)
)
)
)
.Map<Sport>(l => l
.AutoMap()
.Properties(p => p
.Completion(c => c
.Name(n => n.Suggest)
)
)
)
)
);
var bands = new List<Band>
{
new Band { Id = 1, Suggest = new CompletionField<object> { Input = new [] {"Bowling for Soup"} } },
new Band { Id = 2, Suggest = new CompletionField<object> { Input = new [] {"Fastball"} } },
new Band { Id = 3, Suggest = new CompletionField<object> { Input = new [] {"Dropkick Murphys"} } },
new Band { Id = 4, Suggest = new CompletionField<object> { Input = new [] {"Yellowcard"} } },
new Band { Id = 5, Suggest = new CompletionField<object> { Input = new [] {"American Football"} } },
};
client.IndexMany(bands);
var sports = new List<Sport>
{
new Sport { Id = 1, Suggest = new CompletionField<object> { Input = new [] {"Bowling"} } },
new Sport { Id = 2, Suggest = new CompletionField<object> { Input = new [] {"Football"} } },
new Sport { Id = 3, Suggest = new CompletionField<object> { Input = new [] {"Baseball"} } },
new Sport { Id = 4, Suggest = new CompletionField<object> { Input = new [] {"Table Tennis"} } },
new Sport { Id = 5, Suggest = new CompletionField<object> { Input = new [] {"American Football"} } },
};
client.IndexMany(sports);
client.Refresh(defaultIndex);
var suggestResponse = client.Suggest<Band>(s => s
.Completion("suggestion", cs => cs
.Text("Bo")
.Field(f => f.Suggest)
)
);
}
我们从建议电话
取回以下内容{
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"suggestion" : [ {
"text" : "Bo",
"offset" : 0,
"length" : 2,
"options" : [ {
"text" : "Bowling",
"score" : 1.0
}, {
"text" : "Bowling for Soup",
"score" : 1.0
} ]
} ]
}
我们在结果中得到Band
类型和Sport
类型的建议。也许不是我们所期望或想要的,但这就是建议者的工作方式。请注意,在.Suggest<T>()
调用中,类型T
用于提供对可能在查询中使用的属性的强类型访问。在此示例中,.Suggest
类型的Band
字段。
这里推荐的解决方案是为不同类型提供单独的索引;您仍然可以在需要时查询多个索引,并避免在同一索引中存在多个类型时可能出现的陷阱。
除此之外,您可以使用Context Suggester并利用category context完成类型映射来实现此功能。理想情况下,您希望使用文档中存在的类别字段为您提供类别的灵活性,但是您可以根据需要使用元数据字段。我建议您调查和研究您所在领域的方法。
使用前面的示例,如果我们现在在映射中包含类别上下文(与以前相同的代码,但使用此更新的映射)
client.CreateIndex(defaultIndex, ci => ci
.Mappings(m => m
.Map<Band>(l => l
.AutoMap()
.Properties(p => p
.Completion(c => c
.Name(n => n.Suggest)
.Context(sc => sc
.Category("type", csc => csc
// recommend that you use another field on
// the document here instead of a metadata field
.Field("_type")
)
)
)
)
)
.Map<Sport>(l => l
.AutoMap()
.Properties(p => p
.Completion(c => c
.Name(n => n.Suggest)
.Context(sc => sc
.Category("type", csc => csc
// recommend that you use another field on
// the document here instead of a metadata field
.Field("_type")
)
)
)
)
)
)
);
在搜索时使用类别上下文
var suggestResponse = client.Suggest<Band>(s => s
.Completion("suggestion", cs => cs
.Text("Bo")
.Field(f => f.Suggest)
.Context(d => d.Add("type", "band"))
)
);
然后我们得到了理想的结果
{
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"suggestion" : [ {
"text" : "Bo",
"offset" : 0,
"length" : 2,
"options" : [ {
"text" : "Bowling for Soup",
"score" : 1.0
} ]
} ]
}