Elastic Search Date Range Filter lambda expression issue - elasticsearch

Using Nest for ElasticSearch. enter image description here
part of the index looks like this "startdate" : "2018-11-01T00:00:00", "enddate" : "2018-11-01T00:00:00"
My fluentAPI query looks like below
var response = client.Search<ActivityReportsSearchViewModel>(x => x
.Size(500)
.Query(q => q.Bool(b => b.Must
(mu => mu.MultiMatch(m => m
.Fields(n => n.Fields(f => f.User, f => f.Activity
, f => f.County, f => f.Constituency, f => f.Country
, f => f.ActivityRequestDescription, f => f.ActivityDescription,
f => f.LessonsLearnt, f => f.Challenges, f => f.Recommendatinons, f => f.User
, f => f.Venue, f => f.Division))
.Query(**search**)))
.**Filter**(fi => fi
.DateRange(r => r
.Field(f => f.StartDate)
.GreaterThan("2018-08-20")
.LessThanOrEquals(DateMath.Now)
)))));
The query runs well and return results WITHOUT filter. After I add filter as shown above the query returns no results. Can anyone point the problem with the fluentAPI code

You can check response.IsValid to determine whether the request is valid for the API call to Elasticsearch.
The response.DebugInformation will provide more details about the API call in a friendly to read format, including if there is an error. If it is an error in Elasticsearch, response.ServerError will be populated with the details.
Without knowing further details about the response, I suspect the problem is an issue with parsing the string "2018-08-20" as a date on the Elasticsearch server side. Elasticsearch will attempt to parse the string into a date using the format specified in the date field mapping for StartDate, and if the date in the search request is in a different format, you can supply the format in the DateRange query with .Format(...).
Assuming that the document was originally indexed with the .NET client and the default DateTime serialization was used, you should just be able to use an instance of DateTime to supply the needed date
.DateRange(r => r
.Field(f => f.StartDate)
.GreaterThan(new DateTime(2018, 8, 20))
.LessThanOrEquals(DateMath.Now)
)
which will serialize as
"2018-08-20T00:00:00"
which is the same format as the field in the index. Alternatively, you can pass the string in this format.

Related

Query one field with multiple values in elasticsearch nest

I have a combination of two queries with Elasticsearch and nest, the first one is a full-text search for a specific term and the second one is to filter or query another field which is file-path but it should be for many files paths and the path could be part or full path, I can query one file-path but I couldn't manage to do it for many file paths, any suggestion?
Search<SearchResults>(s => s
.Query(q => q
.Match(m => m.Field(f => f.Description).Query("Search_term"))
&& q
.Prefix(t => t.Field(f => f.FilePath).Value("file_Path"))
)
);
For searching for more than one path you can use bool Query in elasticsearch and then use Should Occur to search like logical OR, so you code should look like this:
Search<SearchResults>(s => s
.Query(q => q.
Bool(b => b
.Should(
bs => bs.Wildcard(p => p.FilePath, "*file_Pathfile_Path*"),
bs => bs.Wildcard(p => p.FilePath, "*file_Pathfile_Path*"),
....
))
&& q.Match(m => m.Field(f => f.description).Query("Search_term")
)));
Also you should use WildCard Query to get result for paths that could be part or full path. For more information check ES offical documentation about WildQuery and Bool Query below:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/bool-queries.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html

ElasticSearch NEST multi match returns all result

I have this C# code which is expected to match 2 fields using multi-match Elastic Search type. I am using NEST package.
var response = await _elasticClient.SearchAsync<FileDocument>(
s => s.Query(q => q.MultiMatch(c => c
.Fields(f => f.Field(p => p.FileName).Field(query))
.Fields(f => f.Field(p => p.Metadata).Field(query))
)));
Problem is no matter what text I passed in, it returns all the result. Anything I miss out?
In order to efficiently debug these types of issue, you need to inspect the HTTP request going to Elasticsearch, ultimately your query builder will be converted to search JSON and will be executed against Elasticsearch.
I am not aware of nest but have written the answer for Java code, which prints the Elasticsearch query in JSON format.
Although my guess is that, you are not sending the correct HTTP method which should be POST and you might be sending it with GET, which is causing ES to ignore your search query and return all documents.
Solved after adding .Query(query)
var response = await _elasticClient.SearchAsync<FileDocument>(
s => s.Query(q => q.MultiMatch(c => c
.Fields(f => f.Field(p => p.FileName).Field(p=>p.Metadata))
.Query(query)
))
);
Reference - https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/multi-match-usage.html

Using which field matched in a multimatch query in a function score

I have a multimatch query which I am using across 5 fields. I am also using a function score to combine various factors into the score. I would like to add a factor to this so that results that matched on one of the fields is increased (adding a large number so that matches on this field always have the highest score).
I know that I can use highlighting to find out which fields were matched, but how can I access that information in the function score script?
Here's what I have so far (using NEST, but that shouldn't make a difference).
var searchResponse = client.Search<TopicCollection.Topic>(s => s
.Query(q => q
.FunctionScore(fs => fs
.Name("function_score_query")
.Query(q1 => q1
.MultiMatch(c => c
.Fields(f => f
.Field(p => p.field1)
.Field(p => p.field2) //...etc
.Query(searchTerm)
)
)
.Functions(fun => fun
.ScriptScore(ss => ss.Script(sc => sc
.Inline(
//TODO: add 1000 to normalised _score if match is in field1
)))
).BoostMode(FunctionBoostMode.Replace)
)
).Highlight(h => h
.Fields(p => p.AllField())
)
);

Is it possible to query aggregations on NEST for multiple term fields (.NET)?

Below is the NEST query and aggregations:
Func<QueryContainerDescriptor<ConferenceWrapper>, QueryContainer> query =
q =>
q.Term(p => p.type, "conference")
// && q.Term(p => p.conference.isWaitingAreaCall, true)
&& q.Range(d => d.Field("conference.lengthSeconds").GreaterThanOrEquals(minSeconds))
&& q.DateRange(qd => qd.Field("conference.firstCallerStart").GreaterThanOrEquals(from.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")))
&& q.DateRange(qd => qd.Field("conference.firstCallerStart").LessThanOrEquals(to.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")));
Func<AggregationContainerDescriptor<ConferenceWrapper>, IAggregationContainer> waitingArea =
a => a
.Terms("both", t => t
.Field(p => p.conference.orgNetworkId) // seems ignore this field
.Field(p => p.conference.isWaitingAreaCall)
// .Field(new Field( p => p.conference.orgNetworkId + "-ggg-" + p.conference.networkId)
.Size(300)
.Aggregations(a2 => a2.Sum("sum-length", d2 => d2.Field("conference.lengthSeconds"))));
I have called .Field(p => p.conference.orgNetworkId) followed by .Field(p => p.conference.isWaitingAreaCall) But it seems the NEST client tries to ignore the first field expression.
Is is possible to have multiple fields to be the terms group by?
Elasticsearch doesn't support a terms aggregation on multiple fields directly; the calls to .Field(...) within NEST are assignative rather than additive, so the last call will overwrite any previously set values.
In order to aggregate on multiple fields, you can either
Create a composite field at index time that incorporates the values that you wish to aggregate on
or
Use a Script to generate the terms on which to aggregate at query time, by combining the two field values.
The performance of the first option will be better than the second.

How to : ElasticSearch .NET and NEST 5.X Multimatch with wildcard

I has been search a lot of sample from Internet, however i still could not find any sample on Wildcard Search with more than one fields, can anyone help me with some example? Im very new into ElasticSearch. Below is what im trying to do with wildcard, but it work for one field.
How can i combine below Wildcard with MultiMatch in C#?
var result = client.Search<Metadata>(x => x
.Index("indexname")
.Type("Metadata")
.MatchAll()
.Query(q => q
.Wildcard(c => c
.Name("Query")
.Boost(1.1)
.Field(p => p.Title)
.Value("input*")
.Rewrite(MultiTermQueryRewrite.TopTermsBoost(10))
)
)
);
How can i add in below multi fields support like in Multimatch?
.Fields(f => f
.Fields(f1 => f1.Title, f2 => f2.Keywords)
)

Resources