ElasticSearch (NEST) Query to exclude specific term results - c#

I'm trying to find a QueryContainer query that I can perform on an ElasticSearch result that will essentially filter out any "A" status Items in my resultset. My ProductIndex document contains a field named "StatusCode", and I don't want to return these "A" status' to my search resultsets... I'm having the hardest time finding a way to remove these items.
This query properly finds these "A" status':
.Match(qm => qm
.Field(f => f.StatusCode)
.Query("A"));
But I want to do the opposite (not get all the "A" status items, but exclude them)
Based upon other threads I read on here, I came up with the following query, but it's not filtering out these results:
.Bool(b => b
.MustNot(mn => mn
.Terms(t => t
.Field(f => f.StatusCode)
.Terms("A")
)
));
and
.Bool(b => b
.MustNot(mn => mn
.Term(t => t
.Field(f => f.StatusCode).Value("A")
)
));
But neither removes results that have an "A" statuscode
Kibana value of a result that is still being returned, but has the status "A" code:

The MustNot filter continues to not work for me - I ended up resolving this by performing two search queryies - one based upon the result set obtained from from the first query
.Match(qm => qm
.Field(f => f.StatusCode)
.Query("A"));
This properly filtered the items to only return the ones I was trying to remove from my primary query. I obtained this document list, then applied this list as an exclusion filter to my underlying request, thus filtering out the items I no longer wanted to return.
Not as elegant as I would like, but got the job done.

Related

Elasticsearch: Nest, include match to the search query if variable has value

I have a search query that needs to perform search depending on the provided parameters that are cultureName and the user input that will be string called query. But there is one more 'potential' search condition that needs to be satisfied if value to the variable is provided.
_elasticClient.Search<Document>(s => s
.Size(10)
.Query(q =>
q.Match(m => m.Field(p => p.Culture).Query(cultureName))
&& q.QueryString(queryDescriptor => queryDescriptor
.Query(query)
.Fields(fs => fs
.Fields(f1 => f1.Content)
)
)
)
);
What do I need to use so I can have elastic search matching by one more rule if value is provided and not including the condition when there is no value?
Let's say the incoming variable is called type and needs to match a property called Type in the Document structure I have just the same way there is Content.

C# elastic search query, match multiple queries

I have 2 elastic search queries that need to be matched by each fetched document in different ways. The "pools" query is a terms query. Each document has a list of pools attached to it, each of them being a string, and at least one of those pools must be in the provided list of pools in the "pools" query.
The other query is actually composed of multiple queries and at least 75% percent of them should be matched.
So in order for a document to be matched, the "pools" query must always be matched and from the other query, at least 75% must be matched.
I wrote my query like this:
var matchQuery = BuildQuery(searchCriteria);
var poolQuery = BuildPoolsQueryField(searchCriteria);
// prepare the data for elasticsearch
var result = await _elasticSearchClient.SearchAsync<ElasticPersonEntity>(
p => p.Query(q => q
.Bool(b => b.Must(poolQuery).Should(matchQuery.ToArray())
.MinimumShouldMatch(MinimumShouldMatch.Percentage(75))))).ConfigureAwait(false);
But I could not find anywhere on the internet if you can chain multiple Should and Must clauses and what it happens if you chain them like this.
According to your description, your query is wrong: you need to mustpoolQuery && matchQuery(75%) so
The .MinimumShouldMatch(MinimumShouldMatch.Percentage(75) should be inside your matchQuery :
I join an example (using my data, but this should solve your problem)
.Query(q => q
.Bool(b => b
.Must(
mu => mu.Term(te => te.CntCd, "FR"),
mu => mu.Bool(bo => bo
.Should(your should query).MinimumShouldMatch(75)
)
)
)
)

C# LINQ Filter deep nested list

I've a structure based of list containing other list. I need to filter the list based on the value of a property based in the deepest part of the list.
Right now I'm doing this:
queryable = queryable
.Include(x => x.Carriers)
.ThenInclude(c => c.CarrierActions)
.ThenInclude(ca => ca.Action)
.ThenInclude(ac => ac.ActionFacts);
queryable = queryable
.Where(x => x.Carriers.Any(
carriers => carriers.CarrierActions.Any(
carrieractions =>
carrieractions.Action.ActionTypeId ==
ActionTypeEnum.DosemeterCalculateDeepDose)));
I join the needed tables, then I filter them based on the ActionTypeId based 3 levels below the top list.
First off all, is it possible to do this in 1 step ( include the filtering with the joins ), second of all, the second part is not working as my list gets empty, but I'm certain that actions with that type get values.
Using .NET Core 2.0.3 btw!
To answer your first part, you can do this
queryable = queryable
.Include(x => x.Carriers)
.ThenInclude(c => c.CarrierActions)
.ThenInclude(ca => ca.Action)
.ThenInclude(ac => ac.ActionFacts)
.Where(x => x.Carriers.Any(
carriers => carriers.CarrierActions.Any(
carrieractions =>
carrieractions.Action.ActionTypeId ==
ActionTypeEnum.DosemeterCalculateDeepDose)))
To your second part, it should be working, id check your data, as this is pretty straight forward

C# NEST ElasticSearch search and highlight all fields in all types

Im new to elastic-stack and want to implement global search on my indexed models and this is what I came up with at the moment:
var response = _client.Search<IndexBase>(s => s
.Type(Types.Type(typeof(A), typeof(B)))
.Query(qry => qry
.Bool(b => b
.Must(m => m
.QueryString(qs => qs
.DefaultField("_all")
.Query(request.Query)))))
.Highlight(h =>
h.Fields(f => f.Field("_all")))
But no highlights is showing up in my hits for documents. What Im doing wrong? How I can retrieve [index, count] pairs for highlighting?
Try replacing "_all" in the highlighter with *
var response = _client.Search<IndexBase>(s => s
.Type(Types.Type(typeof(A), typeof(B)))
.Query(qry => qry
.Bool(b => b
.Must(m => m
.QueryString(qs => qs
.DefaultField("_all")
.Query(request.Query)))))
.Highlight(h =>
h.Fields(f => f.Field("*")))
You are not indexing the fields properly.
In order to perform highlighting, the actual content of the field is required. If the field in question is stored (has store set to true in the mapping) it will be used, otherwise, the actual _source will be loaded and the relevant field will be extracted from it.
The _all field cannot be extracted from _source, so it can only be used for highlighting if it mapped to have store set to true.
Source
Also for any bigger set of data this can cause a performance drop so it's always better to set the search fields in the proper way and know what you are trying to highlight.

How do I construct an ElasticSearch search using NEST with fields from multiple types without magic strings

I'm setting up a system where my search indexed objects are Entities which map back to a normalized SQL database. So on the SQL side I may have a Company which is linked to one or more Company_Address records, as well as Company_Email records, etc. But all of the relevant searchable fields will be in a single Company indexed document tying back to the Company's unique id field.
I'm trying to setup queries which will return the relevant id based on comparing a user provided query string with specific fields in the indexed document. I can do so with a query similar to:
var searchResponse = this.client.Search<Company>(search => search.Query(
s => s.MultiMatch(
m => m.Query(query.QueryString)
.Fields(f => f.Field(c => c.Name).Field("Address1")) // Magic strings go here
.Fuzziness(Fuzziness.Auto)
)).Index<Company>());
I'd like to be able to replace "Address1" with ca.Address1 where ca is a CompanyAddress object. Is there a way to construct a collection of FieldDescriptor objects with multiple backing types and then supply that to the search query?
You can construct a Fields instance in a number of ways:
Building a Fields instance by chaining Field instances, constructing those from member access Lambda expressions on some type T
var searchResponse = this.client.Search<Company>(search => search
.Query(q => q
.MultiMatch(m => m
.Query("query")
.Fields(
Infer.Field<Company>(c => c.Name)
.And<CompanyAddress>(c => c.Address1)
)
.Fuzziness(Fuzziness.Auto)
)
)
.Index<Company>()
);
Using nameof with the Address1 property of CompanyAddress
var searchResponse = this.client.Search<Company>(search => search
.Query(q => q
.MultiMatch(m => m
.Query(query.QueryString)
.Fields(f => f
.Field(c => c.Name)
.Field(nameof(CompanyAddress.Address1))
)
.Fuzziness(Fuzziness.Auto)
)
)
.Index<Company>()
);

Categories