如何使用Nest ElasticSearch在多个索引中进行搜索?

我有两个具有以下映射的索引(我将简化它们的映射):

1)AccountType映射:

 elasticClient.CreateIndex("account", i => i

.Settings(s => s

.NumberOfShards(2)

.NumberOfReplicas(0)

)

.Mappings(m => m

.Map<AccountType>(map => map

.AutoMap()

.Properties(p => p

.Text(c => c

.Name(n => n.Name)

.Analyzer("standard")

)

.Text(c => c

.Name(n => n.Description)

.Analyzer("standard")

)

)

)

)

);

2)ProductType映射:

 elasticClient.CreateIndex("proudct", i => i

.Settings(s => s

.NumberOfShards(2)

.NumberOfReplicas(0)

)

.Mappings(m => m

.Map<ProductType>(map => map

.AutoMap()

.Properties(p => p

.Text(c => c

.Name(n => n.Title)

.Analyzer("standard")

)

.Text(c => c

.Name(n => n.Description)

.Analyzer("standard")

)

)

)

)

);

现在,我有几件事需要弄清楚:

1)首先,有一个索引是一个好主意,在我的情况下是帐户,并且产品是嵌套对象,但是在这里每次我要更新/添加新产品时,我都必须重新索引(更新)整个帐户文件?

2)我的第二个问题是:我想具有搜索功能,因此,如果用户通过在文本框中键入内容进行搜索,则我希望同时获得“帐户”和“产品”的最佳匹配(此处,我将针对产品的名称和说明以及帐户名称和说明,然后获得最佳匹配):

因此,在这里如何使用

搜索多个索引,或者如果不可能从每个索引中获得最佳匹配,然后根据得分从两个结果中获得最佳匹配是一个好主意吗?

PS:这是一个搜索产品内部索引的示例:

        var result = elasticClient.Search<ProductType>(s => s

.Size(10)

.Query(q => q

.MultiMatch(m => m

.Fields(f => f.Field(p => p.Title, 1.5).Field(p => p.Description, 0.8))

.Operator(Operator.Or)

.Query(query)

)

)

);

回答:

1)首先,有一个索引是一个好主意,在我的情况下是帐户,并且产品是嵌套对象,但是在这里每次我要更新/添加新产品时,我都必须重新索引(更新)整个帐户文件?

通常建议每个索引具有一种类型,在Elasticsearch

6.0+中,每个索引只能具有一种类型。如果将产品表示为帐户上的嵌套对象,则向帐户中添加新产品将需要更新整个文档(

在您的应用程序代码中或在Elasticsearch中 )。

2)我的第二个问题是:我想具有搜索功能,因此,如果用户通过在文本框中键入内容进行搜索,则我希望同时获得“帐户”和“产品”的最佳匹配(此处,我将针对产品的名称和说明以及帐户名称和说明,然后获得最佳匹配):

您可以搜索多个索引,查看协变搜索结果的文档;它显示了从一个索引返回多种不同类型的示例(此示例将更新为6.0!),但是可以跨多个索引执行此操作。这是一个例子:

private static void Main()

{

var settings = new ConnectionSettings(new Uri("http://localhost:9200"))

.InferMappingFor<AccountType>(i => i

.IndexName("account")

)

.InferMappingFor<ProductType>(i => i

.IndexName("product")

)

// useful for development, to make the request/response bytes

// available on the response

.DisableDirectStreaming()

// indented JSON in requests/responses

.PrettyJson()

// log out all requests/responses

.OnRequestCompleted(callDetails =>

{

if (callDetails.RequestBodyInBytes != null)

{

Console.WriteLine(

$"{callDetails.HttpMethod} {callDetails.Uri} \n" +

$"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");

}

else

{

Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");

}

Console.WriteLine();

if (callDetails.ResponseBodyInBytes != null)

{

Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +

$"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +

$"{new string('-', 30)}\n");

}

else

{

Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +

$"{new string('-', 30)}\n");

}

});

var client = new ElasticClient(settings);

if (client.IndexExists("account").Exists)

client.DeleteIndex("account");

client.CreateIndex("account", i => i

.Settings(s => s

.NumberOfShards(2)

.NumberOfReplicas(0)

)

.Mappings(m => m

.Map<AccountType>(map => map

.AutoMap()

.Properties(p => p

.Text(c => c

.Name(n => n.Name)

.Analyzer("standard")

)

.Text(c => c

.Name(n => n.Description)

.Analyzer("standard")

)

)

)

)

);

if (client.IndexExists("product").Exists)

client.DeleteIndex("product");

client.CreateIndex("product", i => i

.Settings(s => s

.NumberOfShards(2)

.NumberOfReplicas(0)

)

.Mappings(m => m

.Map<ProductType>(map => map

.AutoMap()

.Properties(p => p

.Text(c => c

.Name(n => n.Title)

.Analyzer("standard")

)

.Text(c => c

.Name(n => n.Description)

.Analyzer("standard")

)

)

)

)

);

client.IndexMany(new[] {

new AccountType { Name = "Name 1", Description = "Description 1" },

new AccountType { Name = "Name 2", Description = "Description 2" },

new AccountType { Name = "Name 3", Description = "Description 3" },

new AccountType { Name = "Name 4", Description = "Description 4" },

});

client.IndexMany(new[] {

new ProductType { Title = "Title 1", Description = "Description 1" },

new ProductType { Title = "Title 2", Description = "Description 2" },

new ProductType { Title = "Title 3", Description = "Description 3" },

new ProductType { Title = "Title 4", Description = "Description 4" },

});

var indices = Indices.Index(typeof(ProductType)).And(typeof(AccountType));

client.Refresh(indices);

var searchResponse = client.Search<object>(s => s

.Index(indices)

.Type(Types.Type(typeof(ProductType), typeof(AccountType)))

.Query(q => (q

.MultiMatch(m => m

.Fields(f => f

.Field(Infer.Field<ProductType>(ff => ff.Title, 1.5))

.Field(Infer.Field<ProductType>(ff => ff.Description, 0.8))

)

.Operator(Operator.Or)

.Query("Title 1")

) && +q

.Term("_index", "product")) || (q

.MultiMatch(m => m

.Fields(f => f

.Field(Infer.Field<AccountType>(ff => ff.Name, 3))

.Field(Infer.Field<AccountType>(ff => ff.Description, 0.3))

)

.Operator(Operator.Or)

.Query("Name 4")

) && +q

.Term("_index", "account"))

)

);

foreach (var document in searchResponse.Documents)

Console.WriteLine($"document is a {document.GetType().Name}");

}

public class ProductType

{

public string Title { get; set; }

public string Description { get; set; }

}

public class AccountType

{

public string Name { get; set; }

public string Description { get; set; }

}

结果是

document is a AccountType

document is a ProductType

document is a AccountType

document is a ProductType

document is a AccountType

document is a AccountType

document is a ProductType

document is a ProductType

这里有很多事情,所以让我解释一下。搜索请求JSON如下所示:

POST http://localhost:9200/product%2Caccount/producttype%2Caccounttype/_search?pretty=true 

{

"query": {

"bool": {

"should": [

{

"bool": {

"must": [

{

"multi_match": {

"query": "Title 1",

"operator": "or",

"fields": [

"title^1.5",

"description^0.8"

]

}

}

],

"filter": [

{

"term": {

"_index": {

"value": "product"

}

}

}

]

}

},

{

"bool": {

"must": [

{

"multi_match": {

"query": "Name 4",

"operator": "or",

"fields": [

"name^3",

"description^0.3"

]

}

}

],

"filter": [

{

"term": {

"_index": {

"value": "account"

}

}

}

]

}

}

]

}

}

}

该搜索是在productaccount索引之间,在producttypeaccounttype类型之间执行的。在titledescription字段上执行multi_match查询,并将其与使用布尔查询的术语查询结合​​,以将查询约束到product索引。术语查询位于过滤器子句中,因为不应为该术语查询计算相关性得分。此布尔查询与另一个布尔查询结合在一起,该布尔查询对namedescription字段执行multi_match查询,并与术语查询组合以将查询约束到account索引。这两个布尔查询使用should子句合并,因为其中一个布尔查询或另一个布尔布尔查询需要匹配。

object作为通用的参数类型的Search<T>()方法调用,因为ProductTypeAccountType不共享一个公共基类(除了object!),其产生的文档集合可以分型。但是,从结果中我们可以看到,NEST实际上已反序列化了类型producttype为的实例的ProductType文档和类型accounttype为的实例的文档AccountType

该查询使用运算符重载来更简洁地组合查询。

以上是 如何使用Nest ElasticSearch在多个索引中进行搜索? 的全部内容, 来源链接: utcz.com/qa/421044.html

回到顶部