In Nest (Elasticsearch), how can I get the raw json mapping of an index? - elasticsearch

I want to check the discrepancies between my current mapping (as in my C# code) and the mapping in the elasticsearch index.
With only:
var res = esClient.GetMapping<EsCompany>();
I get GetMappingResponse object in c#, I will have to compare field by field for equality. Even worse, each field has their own properties, I have to descend into those properties for further comparison.
In my application, I prefer obtaining the raw json of the mapping, and I can easily diff two json objects for equality.
I then tried this:
var res = esClient.Raw.IndicesGetMapping(myIndexName);
But when I read res.Response, I get an AmbiguousMatchException exception.

When you connect to Elasticsearch you can choose to expose the raw response like this:
var client = new ElasticClient(new ConnectionSettings().ExposeRawResponse());
Then you should be able to access the raw json via:
var json = res.ConnectionStatus.ResponseRaw;

Related

Elasticsearch NEST Document count for default index

I am using NEST for Elasticsearch 6 and would like to get the number of documents for the default index.
The documentation refers to the 1.1 version of the API which no longer seems to work.
I have created the connection settings using a default index:
var connectionSettings = new ConnectionSettings().DefaultIndex("test_docs");
When I try the code from the 1.1 api documentation:
var result = client.Count();
I get the following error:
The type arguments for method
'ElasticClient.Count(Func, ICountRequest>)'
cannot be inferred from the usage. Try specifying the type arguments
explicitly.
When I supply a type it is appended to the path. For example:
client.Count<TestDocument>();
Generates a URL of http://localhost:9200/test_docs/testdocument/_count when what I really need is http://localhost:9200/test_docs/_count
For those needing the new way of doing this (like myself). I would use the following to get a count from a specific index.
var countRequest = new CountRequest(Indices.Index("videos"));
long count = (await _ecClient.CountAsync(countRequest)).Count;
You can use
var countResponse = client.Count<TestDocument>(c => c.AllTypes());
which will call the API
GET http://localhost:9200/test_docs/_count

How to convert datatype using Spring Mongo template

In Java I have the following Mongo temlate query which works fine:
query = new Query(where("department.departmentId").is(Integer.valueOf("31")));
since the department.departmentId field in the Mongo database is of type Integer.
Since this is just an example I want to be able to compare any field irrespective of its type with a String value (provided by a web client). So I don't want to use 'valueOf' constructions. I don't want to convert the value.
I tried:
query = new Query(where("department.departmentId").is("31").type(16);
query = new Query(where("department.departmentId").is("31").type(2);
query = new Query(where("department.departmentId").type(16).is("31");
query = new Query(where("department.departmentId").type(2).is("31");
Unfortunately nothing works. Is what I want possible?

Mapping Nest response to a C# object

I am trying to map a nest response to a c# object and having little luck.
My query returns the result from
var resp = Eclient.Search<dynamic>(q => q
.Type("movies")
.From(0)
.Size(20)
.QueryRaw(queryString));
How can I map the response to a C# object?
It needs to be dynamic, i.e there are arrays that wary in length in the response.
Serialize a dynamic object to JSON and then deserialize a string to a proper C# object. But that would be totally inefficient. Why not pass a dynamic object around or just do manual mapping?

How to post json data using West Wind in VFP

There's a document from West Wind says you can post data using application/json format:
https://west-wind.com/webconnection/docs/_2110q21c9.htm
But when using it, actually it'll do a http get instead of post:
DO wwhttp
oHTTP=CREATEOBJECT("wwHttp")
oHTTP.nHTTPPostMode = 8
oHttp.cContentType = "application/json"
oHTTP.AddPostKey("name","somename")
lcURL = "https://mywebserver.com/"
lcXML = oHTTP.HTTPGet(lcURL)
If using nHTTPPostMode = 1 or 2, the http request parameters are not correctly formatted as json. If I change to 4, it's using Get instead of Post again. Is there anyway to get around this?
When you post JSON data you need to post a JSON document not key value pairs as you are doing in your example. Essentially you need to provide the full content - the entire JSON document as a string - that you're sending to the server (just like the example shows).
To post a JSON document looks like this:
DO wwHttp
oHTTP=CREATEOBJECT("wwHttp")
oHttp.cContentType = "application/json"
lcJson = "{ name: 'somename' }"
oHTTP.AddPostKey(lcJson) && this sets the entire post buffer
lcURL = "https://mywebserver.com/"
lcJson = oHTTP.HTTPGet(lcURL)
Using name value pairs only works with POST buffers for URLEncoded or Multipart documents - every other type of content is sent as raw data that you have to provide.
in version 6 and later you can also use the following simpler syntax to .Post data:
oHttp.cContentType = "application/json"
lcJson = oHttp.Post(lcUrl, lcJson)
If you want to create JSON documents under program control you can serialize data using the wwJsonSerializer class (also part of Client Tools). It can serialize from objects, arrays/collections and cursors.

Cannot index document

I have written some code using the Elasticsearch.Net & NEST client library that should index a document without using a POCO for mapping fields as I have many different documents.
Question 1) Is this correct way to do create an index, does the .AddMapping<string>(mapping => mapping.Dynamic(true)) create the mapping based on the document passed in?
var newIndex = client.CreateIndex(indexName, index => index
.NumberOfReplicas(replicas)
.NumberOfShards(shards)
.Settings(settings => settings
.Add("merge.policy.merge_factor", "10")
.Add("search.slowlog.threshold.fetch.warn", "1s")
)
.AddMapping<string>(mapping => mapping.Dynamic(true))
);
Question 2) Is this possible?
string document = "{\"name\": \"Mike\"}";
var newIndex = client.Index(document, indexSelector => indexSelector
.Index(indexName)
);
When I run code in "Question 2" it returns:
{"Unable to perform request: 'POST ' on any of the nodes after retrying 0 times."}
NEST only deals with typed objects in this case passing a string will cause it to index the document into /{indexName}/string/{id}.
Since it can't infer an id from string and you do not pass it one it will fail on that or on the fact that it can't serialize a string. I'll update the client to throw a better exception in this case.
If you want to index a document as string use the exposed Elasticsearch.NET client like so:
client.Raw.Index(indexName, typeName, id, stringJson);
If you want elasticsearch to come up with an id you can use
client.Raw.Index(indexName, type, stringJson);
client is the NESTclient and the Raw property is an Elasticsearch.Net client with the same connectionsettings.
Please note that I might rename Raw with LowLevel in the next beta update, still debating that.

Resources