1) Zuerst es eine gute Idee ist, einen Index zu haben, die in meinem Fall ist Konto und hat Produkte als verschachtelte Objekte , aber hier muss ich jedes Mal, wenn ich ein neues Produkt aktualisieren/hinzufügen möchte, das gesamte Konto neu indizieren (aktualisieren)?
Es wird generell empfohlen, einen Typ pro Index und in Elasticsearch 6.0+, you can only have one type per index zu verwenden. Wenn Produkte als verschachtelte Objekte in einem Konto dargestellt werden, müssen Sie das neue Dokument einem Konto hinzufügen (entweder in Ihrem Anwendungscode oder in Elasticsearch).
2) Meine zweite Frage ist: Ich möchte Suchfunktion haben, so dass, wenn der Benutzer Suche in einem Textfeld, indem Sie würde ich die besten Übereinstimmungen für beide Konten bekommen und Produkte (hier werde ich gegen Titel Produkt suchen und Beschreibung Plus-Konto des Namens und der Beschreibung dann immer am besten Matches):
Sie über mehrere Indizes suchen, überprüfen the documentation of covariant search results; Es zeigt ein Beispiel für die Rückgabe mehrerer verschiedener Typen aus einem Index (dieses Beispiel wird für 6.0 aktualisiert!), aber es ist möglich, dies über mehrere Indizes hinweg durchzuführen. Hier ein Beispiel:
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; }
}
Das Ergebnis ist
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
Es ist viel los hier so lassen Sie mich erklären.Die Suchanfrage JSON wie folgt aussieht:
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"
}
}
}
]
}
}
]
}
}
}
Die Suche über beide product
und account
Indizes ausgeführt wird, über producttype
und accounttype
Typen. In den Feldern title
und description
wird eine Abfrage multi_match ausgeführt, die mit einer Termbuchabfrage mit einer bool-Abfrage kombiniert wird, um die Abfrage auf den Index product
zu beschränken. Der Begriff Abfrage befindet sich in einer Filterklausel, da für die Begriffssuche kein Relevanzwert berechnet werden sollte. Diese bool-Abfrage wird mit einer anderen bool-Abfrage kombiniert, die eine multi_match-Abfrage für die Felder name
und description
ausführt, die mit einer Termabfrage verbunden sind, um die Abfrage auf den account
-Index zu beschränken. Die zwei Bool-Abfragen werden mithilfe von SOLL-Klauseln kombiniert, da entweder eine der Bool-Abfragen oder die andere übereinstimmen muss.
object
wird als generischer Parameter Typ für die Search<T>()
Methodenaufruf verwendet, da ProductType
und AccountType
(außer object
!) Keine gemeinsame Basisklasse teilen die resultierende Dokumentensammlung kann auf dem eingegeben werden. Wir können jedoch aus den Ergebnissen sehen, dass NEST tatsächlich Dokumente mit dem Typ producttype
zu Instanzen von ProductType
und Dokumente mit dem Typ accounttype
zu Instanzen von deserialisiert hat.
Die Abfrage verwendet operator overloading, um Abfragen bündiger zu kombinieren.
Bro Sie sind der Meister von Nest elasticsearch. Jedes Mal, wenn ich eine Frage stelle, erhalte ich eine genaue Antwort von Ihnen. Vielen Dank für Ihre zu detaillierte Antwort. –
Hoffe "wie eine Hölle" ist gut :) Glücklich zu helfen –
Sorry für mein schlechtes Englisch. Es scheint, dass "wie eine Hölle" schlechte Bedeutung hat –