how to write existsQuery in nest 1.7 - elasticsearch

I'm using nest 1.7 and i need to write this query:
GET _search
{
"from": 0,
"size": 3,
"query": {
"bool": {
"must": [
{
"constant_score": {
"filter": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"exists": {
"field": "Collaborateurs"
}
},
{
"exists": {
"field": "Collaborateurs.Nom"
}
},
{
"exists": {
"field": "Collaborateurs.Fonction"
}
},
{
"exists": {
"field": "Collaborateurs.TagVisuel"
}
},
{
"exists": {
"field": "siAnnuaire"
}
},
{
"term": {
"siAnnuaire": {
"value": true
}
}
},
{
"exists": {
"field": "TagPhoto"
}
},
{
"range": {
"NbAnnonce": {
"gt": 0
}
}
},
{
"geo_distance": {
"distance": "10.0km",
"AgenceLocation": {
"lat": 48.8523513700019,
"lon": 2.35127712591128
}
}
}
]
}
}
]
}
}
}
},
{
"function_score": {
"functions": [
{
"random_score": {
"seed": 69937385
}
}
]
}
}
]
}
}
}

Using the fluent API, the method calls follow pretty much the structure of the query DSL json
var response = client.Search<Document>(x => x
.From(0)
.Size(3)
.Query(q => q
.Bool(b => b
.Must(m => m
.ConstantScore(cs => cs
.Filter(csf => csf
.Bool(cb => cb
.Must(
cm => cm.Exists(p => p.Collaborateurs),
cm => cm.Exists(p => p.Collaborateurs.Nom),
cm => cm.Exists(p => p.Collaborateurs.Fonction)
// etc, etc for the other queries
)
)
)
), m => m
.FunctionScore(fs => fs
.Functions(fu => fu
.RandomScore(69937385)
)
)
)
)
)
);
which yields
{
"from": 0,
"size": 3,
"query": {
"bool": {
"must": [
{
"constant_score": {
"filter": {
"bool": {
"must": [
{
"exists": {
"field": "collaborateurs"
}
},
{
"exists": {
"field": "collaborateurs.nom"
}
},
{
"exists": {
"field": "collaborateurs.fonction"
}
}
]
}
}
}
},
{
"function_score": {
"functions": [
{
"random_score": {
"seed": 69937385
}
}
]
}
}
]
}
}
}
field names have been camel-cased by default, but you can change this behaviour using .SetDefaultPropertyNameInferrer(Func<string, string>) on ConnectionSettings.

Related

Complex nested Elastic NEST Query

How would I convert this to the equivalent Nest query?
{
"query": {
"nested": {
"path": "boundedContexts",
"query": {
"nested": {
"path": "boundedContexts.aggregateRoots",
"query": {
"nested": {
"path": "boundedContexts.aggregateRoots.modelMetaData",
"query": {
"bool": {
"must": [
{ "match": { "boundedContexts.aggregateRoots.modelMetaData.modelReferenceId": "4e7c5c0e-93a7-4bf6-9705-cf1327760e21" } },
{ "match": { "boundedContexts.aggregateRoots.modelMetaData.modelType.name": "AggregateRoot" } }
]
}
}
}
}
}
}
}
},
"size": 1,
"sort": [
{
"generatedDate": {
"order": "desc"
}
}
]
}
I am trying to generate an equivalent Nest query similar to this ..
ISearchResponse<ViewModels.DomainModel> response = null;
response = await _elasticClient.SearchAsync<ViewModels.DomainModel>(s => s.Index(_modelMetadataProvider.CurrentIndexName)
.Query(q => q.Nested(n1 => n1.Path("boundedContexts")
.Query(q2 => q2.Nested(n2 => n2.Path("boundedContexts.aggregateRoots")
.Query(q3 => q3.Nested(n3 => n3.Path("boundedContexts.aggregateRoots.modelMetaData").
Query(q4 =>q4.Bool(b => b.Must(bs =>
bs.Match(p => p.Field("boundedContexts.aggregateRoots.modelMetaData.modelReferenceId")))))))))))
.Size(1).Sort(s=>s.Descending("generatedDate")));
I am stuck on how to compare to a variable against at the p.Field("boundedContexts.aggregateRoots.modelMetaData.modelReferenceId") level of query.

Elastic search - handling the condition using must or must not query

We have a requirement if newId is there then we have to get the data less than todays date
and if newId field is not there in the data then we have to get the data till expiry date + 2Months.
I was trying below query but result has not come as expected.
{
"id":"234",
"startDate":"23/07/2020",
"endDate":"24/09/20202",
"newId":"2345"
},
{
"id":"234",
"startDate":"23/07/2020",
"endDate":"24/09/20202",
"newId":null
},
{
"id":"235",
"startDate":"23/07/2020",
"endDate":"24/06/2020",
"newId":"2345"
},
Query that I was trying
{
"query": {
"bool": {
"must": [
{
"match_all": {}
},
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"exists": {
"field": "newId"
}
},
{
"range": {
"endDate": {
"gte":"now/d"
}
}
}
]
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "newId"
}
},
{
"range": {
"endDate": {
"gte": "now-2M"
}
}
}
]
}
}
]
}
}
]
}
}
}
Expected result
{
"id":"234",
"startDate":"23/07/2020",
"endDate":"24/09/20202",
"newId":"2345"
},
{
"id":"234",
"startDate":"23/07/2020",
"endDate":"24/09/20202",
"newId":null
},
Great start! Your query is almost right, but you need a few more tweaks, namely to use should instead of must, because both sub-queries will never be true at the same time:
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"exists": {
"field": "newId"
}
},
{
"range": {
"endDate": {
"gte": "now/d"
}
}
}
]
}
},
{
"bool": {
"must": [
{
"range": {
"endDate": {
"gte": "now-2M"
}
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "newId"
}
}
]
}
}
]
}
}
]
}
}
}

Elasticsearch- nested conditional statements

I would like to develop multiple if else condition like this :
if(condition 1)
{
process 1
}
else
{
if(condition 2.1)
{
process 2
}
else (condition 2.2)
{ process 3
}
}
is bool with must and should the optimized way to do it or can script be used? As my query is already huge, since it has fuzziness and wildcard already.
Thanks
I think you can use painless script query for your use case. Bool must query will not work in this case I think.
You can refer this page for how to use if else in the script query
.https://www.elastic.co/guide/en/elasticsearch/painless/6.0/painless-examples.html
GET /books/_search
{
"_source": [
"id",
"name",
"user",
"privacy"
],
"query": {
"bool": {
"must": [
{
"term": {
"status": {
"value": 1
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{ //if
"bool": {
"must": [
{
"term": {
"user.privacy.mode": {
"value": 0
}
}
},
{
"term": {
"privacy.mode": {
"value": 0
}
}
}
]
}
},
{//else if
"bool": {
"must": [
{
"term": {
"user.privacy.mode": {
"value": 2
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{// if
"nested": {
"path": "readers",
"query": {
"match": {
"readers.id": "621120dc86b8920019295363"
}
}
}
},
{ // else
"nested": {
"path": "buyers",
"query": {
"match": {
"buyers.purchase.id": "621120dc86b8920019290f50"
}
}
}
}
]
}
}
]
}
},
{// else if
"bool": {
"must": [
{
"term": {
"privacy.mode": {
"value": 2
}
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"nested": {
"path": "readers",
"query": {
"match": {
"readers.id": "621120dc86b89200195373"
}
}
}
},
{
"nested": {
"path": "buyers",
"query": {
"match": {
"buyers.purchase.id": "621120dc86b892001929036350"
}
}
}
}
]
}
}
]
}
}
]
}
}
],
"filter": {
"bool": {
"must_not": [
{
"term": {
"user.privacy.mode": 1
}
},
{
"term": {
"privacy.mode": 1
}
}
]
}
}
}
}
}

Filter Creation

So after much experimentation I have found that the syntax I needed to filter products based on their specs is as follows
{
"post_filter": {
"bool": {
"filter": [{
"nested": {
"path": "productSpecification",
"query": {
"bool": {
"filter": [{
"term": {
"productSpecification.name": "Brand"
}
},
{
"terms": {
"productSpecification.value": [
"Brand1"
]
}
}
]
}
}
}
},
{
"nested": {
"path": "productSpecification",
"query": {
"bool": {
"filter": [{
"term": {
"productSpecification.name": "Guarantee"
}
},
{
"terms": {
"productSpecification.value": [
"3 years"
]
}
}
]
}
}
}
}
]
}
}
}
I'm now experimenting with creating a QueryContainer function to build this based on the selected name/values, If anyone can give me a point in the right direction on this that would be much appreciated.
Thanks
Ok I am now building a query from nest that works but is a bit messier than the DSL query above (not sure if someone can spot what Im doing below that makes it have some unnecessary bool filters
Here is my nest syntax
.PostFilter(pf => FilterTest(elasticParams,pf))
private static QueryContainer FilterTest(ElasticParams elasticParams, QueryContainerDescriptor<Product>q) => q
.Bool(b => b
.Filter(fi => FilterSelected(elasticParams, fi)));
private static QueryContainer FilterSelected2(ElasticParams elasticParams, QueryContainerDescriptor<Product> q) =>
elasticParams.Filters.Aggregate(new QueryContainer(), (c, s) => c && +q.Nested(n => n
.Path(p => p.ProductSpecification)
.Query(qq => qq
.Bool(bo => bo
.Filter(fi => fi
.Term(tt => tt
.Field(a => a.ProductSpecification.Suffix("name"))
.Value(s.name)) && fi
.Terms(ttt => ttt
.Field(fff => fff.ProductSpecification.Suffix("value"))
.Terms(s.Values))
)))));
As mentioned before this is filters as I would want however it DSL that it outputs is rather fugly as can be seen below
{
"post_filter": {
"bool": {
"filter": [{
"bool": {
"filter": [{
"nested": {
"query": {
"bool": {
"filter": [{
"bool": {
"must": [{
"term": {
"productSpecification.name": {
"value": "Brand"
}
}
}, {
"terms": {
"productSpecification.value": ["Brand1", "Brand2"]
}
}]
}
}]
}
},
"path": "productSpecification"
}
}, {
"nested": {
"query": {
"bool": {
"filter": [{
"bool": {
"must": [{
"term": {
"productSpecification.name": {
"value": "Guarantee"
}
}
}, {
"terms": {
"productSpecification.value": ["3 years"]
}
}]
}
}]
}
},
"path": "productSpecification"
}
}]
}
}]
}
}
}

Multiple bool clauses in elasticsearch filter/query

How should I translate this SQL query into an elasticsearch query?
SELECT * FROM myTable WHERE (id = 99 AND isonline <> 1) OR (id = 98 AND isonline <> 0)
How do I make a query that has multiple bool filters? (bonus would be to also show how to do it in NEST)
The elastic query I've come up with doesn't work because it contains duplicate object keys.
{
"size": 1000,
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"term": {
"id": 99
}
}
],
"must_not": [
{
"term": {
"isonline": true
}
}
]
},
"bool": {
"must": [
{
"term": {
"id": 98
}
}
],
"must_not": [
{
"term": {
"isonline": false
}
}
]
}
}
}
elasticsearch version 1.7
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"id": 99
}
},
{
"term": {
"isonline": false
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"id": 98
}
},
{
"term": {
"isonline": true
}
}
]
}
}
]
}
}
}

Resources