Je voudrais faire une requête ElasticSearch comme ceci:
{
"query" :
{
"bool" :
{
"filter" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
}
J'ai essayé de l'implémenter dans NEST comme ceci:
_elasticClient
.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(fq =>
{
QueryContainer query = null;
if (nameList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Name).Terms(nameList));
}
if (colorList.Any()) {
query &= fq.Terms(t => t.Field(f => f.Color).Terms(colorList));
}
return query;
})
)
)
);
Mais cela me donne une requête comme celle-ci où les filtres sont encapsulés dans un bool must :
{
"query" :
{
"bool" :
{
"filter" : [
{
"bool" :
{
"must" : [
{
"terms" :
{
"name" : ["name1", "name2"]
}
},
{
"terms" :
{
"color" : ["orange", "red"]
}
}
]
}
}
]
}
}
}
Comment dois-je changer mon code NEST pour me donner la bonne requête? Dois-je ajouter mes termes à quelque chose d'autre qu'un QueryContainer ?
Vous pouvez créer une liste de filtres avant de faire une requête si vous souhaitez vérifier les filtres conditionnels comme indiqué ci-dessous:
var nameList = new[] {"a", "b"};
var colorList = new[] {1, 2};
var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>();
if (nameList.Any())
{
filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList)));
}
if (colorList.Any())
{
filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)));
}
ISearchResponse<Property> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq.Filter(filters))));
Si vous n'avez besoin de vérifier aucune condition avant de créer une requête de filtrage, vous pouvez avoir quelque chose comme ça:
ISearchResponse<MyDocument> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
))));
La méthode Filter
d'une requête bool utilise un params Func<QueryContainerDescriptor<T>, QueryContainer>[]
afin que vous puissiez lui transmettre plusieurs expressions pour représenter plusieurs filtres.
var nameList = new string[] { "name1", "name2" };
var colorList = new string[] { "orange", "red" };
client.SearchAsync<MyDocument>(s => s
.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
)
)
)
);
qui se traduit par
{
"query": {
"bool": {
"filter": [
{
"terms": {
"name": [
"name1",
"name2"
]
}
},
{
"terms": {
"color": [
"orange",
"red"
]
}
}
]
}
}
}
NEST utilise également le concept de requêtes sans condition , c'est-à-dire que si une requête est considérée comme étant sans condition, elle sera not sera sérialisée dans le cadre de la requête.
Qu'est-ce que cela signifie d'être sans condition? Cela dépend de la requête. par exemple, dans le cas d'une requête terms
, elle est considérée comme étant sans condition si l'une des conditions suivantes est vraie
field
n'a pas de valeur null
null
ou videsDémontrer
var emptyNames = new string[] {};
string[] nullColors = null;
client.SearchAsync<MyDocument>(s =>
s.Index("myindex")
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)),
fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors)))
)
)
);
résulte en
{}
Les requêtes sans condition servent à faciliter l'écriture des requêtes NEST dans la mesure où vous n'avez pas besoin de vérifier si la collection a des valeurs avant de construire une requête. Vous pouvez modifier la sémantique sans condition sur la base d'une requête à l'aide de .Strict()
et de .Verbatim()
.
var searchResponse = client.Search<EventData>(s => s
.From(0)
.Query(q => q
.Bool(bq => bq
.Filter(
fq => fq.Terms(t => t.Field(f => f.Client.Id).Terms(17)),
fq => fq.Terms(t => t.Field(f => f.Item.Id).Terms(**new[] { 34983, 35430, 35339, 35300 }**)),
fq => fq.Terms(t=>t.Field(f=>f.Event).Terms("Control de Panico")),
fq => fq.DateRange(dr => dr.Field(f => f.DateTime)
.GreaterThanOrEquals(new DateTime(2018, 07, 01))
.LessThanOrEquals(new DateTime(2018, 10, 02)))
)
))
.Size(2000)
.Sort(g => sortDescriptor)
);