我要求提供正常工作的建议,但我还需要通过文档中的其他字段过滤建议。
这有可能实现吗?只要我知道,Elasticsearch就无法做到这一点。还有其他想法吗?
public async Task<ISuggestResponse> Suggest(string index, string projectId, string field, string text)
{
var suggestResponse = await _client.SuggestAsync<TDocument>(s => s
.Index(index)
.Completion("suggest", c => c
.Text(text)
.Context(con => con.Add("projectId", projectId))
.Field(field)
.Size(20)
)
);
return suggestResponse;
}
-----------更新--------------------
ElasticsearchConfig.cs
client.Map<Component>(d => d
.Properties(props => props
.String(s => s
.Name("name"))
.Completion(c => c
.Name("componentSuggestion")
.Analyzer("simple")
.SearchAnalyzer("simple")
.Context(context => context
.Category("projectId", cat => cat
.Field(field => field.ProjectId)))
.Payloads()))
.Properties(props => props.String(s => s.Name("id").NotAnalyzed()))
.Properties(props => props.String(s => s.Name("projectId").NotAnalyzed())));
答案 0 :(得分:3)
The Context Suggester 扩展了完成建议器,以便在类别或地理位置上提供基本过滤元素。这可能足以满足您的目的。
您可能想要采用的另一种方法是使用Context Suggester提供按类型搜索的建议,在完成类型映射的有效负载内索引每个文档的id;然后使用有效负载中返回的ID来搜索文档,此时应用您的附加过滤并仅返回与过滤匹配的文档ID。最后,使用这些文档ID来获取原始建议响应中的建议。
修改强>
以下是使用Context Suggester
的完整示例void Main()
{
var componentsIndex = "components";
var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(connectionPool)
// use component index when working with
// Component Poco type
.InferMappingFor<Component>(m => m
.IndexName(componentsIndex)
);
var client = new ElasticClient(settings);
// make this example repeatable, so delete index if
// it already exists
if (client.IndexExists(componentsIndex).Exists)
client.DeleteIndex(componentsIndex);
// for example purposes, only use one shard and no replicas
// NOT RECOMMENDED FOR PRODUCTION
client.CreateIndex(componentsIndex, c => c
.Settings(s => s
.NumberOfShards(1)
.NumberOfReplicas(0)
)
);
client.Map<Component>(d => d
.Index(componentsIndex)
// infer mapping of fields from property of the POCO.
// This means we don't need to explicitly specify all
// mappings in .Properties()
.AutoMap()
// Now, override any inferred mappings from automapping
.Properties(props => props
.Completion(c => c
.Name(n => n.ComponentSuggestion)
.Context(context => context
.Category("projectId", cat => cat
.Field(field => field.ProjectId)
)
)
.Payloads()
)
.String(s => s
.Name(n => n.Id)
.NotAnalyzed()
)
.String(s => s
.Name(n => n.ProjectId)
.NotAnalyzed()
)
)
);
var components = new[] {
new Component
{
Id = "1",
Name = "Component Name 1",
ComponentSuggestion = new CompletionField<object>
{
Input = new [] { "Component Name 1" },
Output = "Component Name 1"
},
ProjectId = "project_id"
},
new Component
{
Id = "2",
Name = "Component Name 2",
ComponentSuggestion = new CompletionField<object>
{
Input = new [] { "Component Name 2" },
Output = "Component Name 2"
},
ProjectId = "project_id_2"
}
};
// index some components with different project ids
client.IndexMany(components);
// refresh the index to make the newly indexed documents available for
// search. Useful for demo purposes but,
// TRY TO AVOID CALLING REFRESH IN PRODUCTION
client.Refresh(componentsIndex);
var projectId = "project_id";
var suggestResponse = client.Suggest<Component>(s => s
.Index(componentsIndex)
.Completion("suggester", c => c
.Field(f => f.ComponentSuggestion)
.Text("Compon")
.Context(con => con.Add("projectId", projectId))
.Size(20)
)
);
foreach (var suggestion in suggestResponse.Suggestions["suggester"].SelectMany(s => s.Options))
{
Console.WriteLine(suggestion.Text);
}
}
public class Component
{
public string Id { get; set; }
public string Name { get; set; }
public string ProjectId { get; set; }
public CompletionField<object> ComponentSuggestion { get; set; }
}
根据Component Name 1
projectId
"project_id"
答案 1 :(得分:2)
您应该使用context suggester而不是完成建议器,其目标是允许您为完成建议者指定其他类别或地理位置上下文。
如果我没弄错的话,NEST通过Context
属性提供上下文建议器作为完成建议器的一部分。
public async Task<ISuggestResponse> Suggest(string index, string field, string text)
{
var suggestResponse = await _client.SuggestAsync<TDocument>(s => s
.Index(index)
.Completion("suggest", c => c
.Text(text)
.Context(con => con.Add("your_field", "text"))
.Field(field)
.Size(20)
)
);
return suggestResponse;
}
您还需要更改映射中的完成字段,以声明上下文。