Using Elasticsearch Nest 7.x to query 5.x index - elasticsearch

I have a project using Nest 7.x and there is a query I need to make to an older 5.x elasticsearch index. When I make a call like this, I get the following error. I am guessing it is due to how the mapping types were changed in version 6 and greater. Is there any way around this to query an older index?
var result = _elasticClient.GetAsync<Category>(id)
Invalid NEST response built from a successful (404) low level call on
GET: /myindex/_doc/15437
Request: <Request stream not captured or already read to completion by serializer. Set DisableDirectStreaming() on ConnectionSettings to
force it to be set on the response.>
Response: {"_index":"2020-01-13","_type":"_doc","_id":"15437","found":false}

As a workaround, I did this and it appears to work. Not sure if there are any better solutions?
var response = _elasticClient.SearchAsync<Category>(s => s
.Query(q => q
.Bool(b => b
.Must(
bs => bs.Term(p => p.Id, id),
bs => bs.Term(p => p.Field("_type").Value("category"))
)
)
)
)

Related

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

NEST MultiGet search all types possible?

I have got unique document ids (across all types) and I would like to check which document already exists in elasticsearch index. I try to search
var duplicateCheck = _elasticClient
.MultiGet(m => m.GetMany<object>(notices.Select(s => s.Id)).Fields("Id"));
but it returns wrong result - every document has set found property to false.
update
there is workaround here
var exisitngDocIds = _elasticClient.Search<ZPBase>(s => s
.AllTypes()
.Query(q => q.Ids(notices.Select(z=>z.Id)))
.Fields("Id")
.Take(notices.Count)
);
notices = notices.Where(q => !exisitngDocIds.Hits.Any(s => s.Id == q.Id)).ToList();
From the Multi Get API documentation I realized that you can use something similar to the following code to solve your problem:
var response = _elasticClient.MultiGet(m => m
.Index(MyIndex)
.Type("")
.GetMany<ZPBase>(noticeIds));
Note the empty string passed as the Type.

MatchPhrasePrefix on NEST Elastic Search

I cannot figure out how to search the documents in my index by the MatchPhrasePrefix. I want to match on the entire search term phrase, but allow prefixes on the last term.
This LINQ construction is giving me back everything with a score of 1.0. How would I construct this? On a side note, is there anyway to see the raw query that NEST is constructing? That would be very helpful!
var search = new SearchDescriptor<ObservationElasticModel>();
search = search
.Query(q => q.MatchPhrase(m => m.Query(term)));
var response = _client.Search<ObservationElasticModel>(search);
You can use the MatchPhrasePrefix method on the QueryDescriptor. You may also need to set the Operator to AND.
_client.Search<ObservationElasticModel>(s => s
.Query(q => q
.MatchPhrasePrefix(m => m
.Operator(Operator.And)
.Query(term)));
You can log raw queries to the debugging console by calling EnableTrace() and ExposeRawResponse() on the ConnectionSettings instance during setup.
var settings = new ConnectionSettings(new Uri(searchUri));
settings.EnableTrace();
settings.ExposeRawResponse();
_client = new ElasticClient(settings);

Set Elasticsearch timestamp path on an index using NEST?

I need to add a timestamp path to my index using NEST, not sure how to make this happen:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-timestamp-field.html
I have been messing with NEST but I cannot figure this out.
I have been reading the docs here but have not found what i am looking for:
http://nest.azurewebsites.net/nest/quick-start.html
Using the fluent API, this can be done when creating your index:
var response = client.CreateIndex("myindex", c => c
.AddMapping<MyType>(m => m
.MapFromAttributes()
.TimestampField(t => t
.SetDisabled(false)
.SetPath(o => o.MyTimestampField)
)
)
);
Or updating an existing index:
var response = client.Map<MyType>(m => m
.TimestampField(t => t
.SetDisabled(false)
.SetPath(o => o.MyTimestampField)
)
);
Hope that helps.

How to construct filter for Elastic Search on Log Stash with NEST?

I have a logstash/elasticsearch/kibana system set up and structured json type logs are getting into elastic search (not from a C# application) and visible in kibana.
I am using NEST because I would like to slice the data from logstash.
The following code is producing "hits" results that I can inspect in the debugger.
ElasticClient client = new ElasticClient(settings);
var searchResults = client.Search( s => s
.From(0)
.Size(100)
.AllIndices()
.SortDescending("#timestamp")
);
However, if I try to expand the search to include something I believe to be present in the log (visible in Kibana), I get now results.
var searchResults = client.Search( s => s
.From(0)
.Size(100)
.AllIndices()
.Query(q => q
.Term("MySpecialFieldName", "ValueThatAppears")
)
.SortDescending("#timestamp")
);
I would also like to take advantage of the type safety and other mechanisms shown in the samples. I am not sure if that is expected to be related.
( I am working on figuring that out separately: Adding a class like "client.Search( to the search seems to prevent the results as well, I am assuming that something about the class is not aligned with the data and is therefore unable to deserialize or is otherwise filtering...)
Found the correct settings to make this work:
The logstash system puts this into a type (log or logs I think) when it gets indexed by elastic search. Also the term needs to be suffixed with ".raw". So the working example ends up being:
var searchResults = client.Search<MyClass>( s => s
.From(0)
.Size(100)
.AllIndices()
.AllTypes()
.Query(q => q
.Term("MySpecialFieldName.raw", "ValueThatAppears")
)
.SortDescending("#timestamp")
);

Resources