Combining fluent and object initializer syntax - elasticsearch

Using the .NET client NEST, is it possible to combine the two syntaxes like below where the Query is written in one syntax and the Aggregation in another?
var request = new SearchRequest();
request.Query = new MatchAllQuery();
request.Aggregations = new AggregationContainerDescriptor<Car>().Terms("color", x => x.Field(doc => doc.Color));
_elasticClient.Search<Car>(request);
The compile error here being that a AggregationContainerDescriptor is not assailable to a AggregationDictionary

You can cast your descriptor to IAggregationContainer and get Aggregations from there:
var request = new SearchRequest();
request.Query = new MatchAllQuery();
var aggregationContainer = (IAggregationContainer)new AggregationContainerDescriptor<Car>().Terms("color", x => x.Field(doc => doc.Color));
request.Aggregations = aggregationContainer.Aggregations;
var searchResponse = _elasticClient.Search<Car>(request);
Hope that helps.

Related

ef6 linq method returning $ref for nested entries in query

my linq method system from EF6 is returning $ref when I monitor results in fiddler. If I watch the local window in my webapi everything is populated correctly, but not in the actual results that are returned. It only affects the nested entries. anyone know what I am doing wrong? (I created models from database in EF6)
var student = dbEF.Accounts
.Where(x => x.AccountNumber == acctNum)
.Select(x => new DTOCrmDetails()
{
AccountNumber = x.AccountNumber,
CommissionId = x.CommissionId,
Commission = x.Commission,
ManagerID = x.ManagerID,
ManagerName = x.Manager.ManagerName,
Manager = x.Manager,
Employees = x.Manager.Employees,
WireInstructionsUSD = x.Manager.WireInstructionsUSDs
//Mapping_ManagersExecutingBrokers = x.Manager.Mapping_ManagersExecutingBrokers
}).FirstOrDefault();
return student;
these are my settings.
var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
You need to disable your lazy loading in the entity framework dbcontext.
something like this way:
dbEF.Configuration.LazyLoadingEnabled = false;

QueryContainerDescriptor vs QueryContainer vs QueryBase

Can anyone explain what is the difference between QueryContainerDescriptor, QueryContainer & QueryBase?
How can I assign a query (or QueryBase) to QueryContainer?
In the code below, I can assign the same TermQuery to QueryBase and QueryContainer objects:
QueryBase bq = new TermQuery
{
Field = Field<POCO>(p => p.Title),
Value = "my_title"
};
QueryContainer tq = new TermQuery
{
Field = Field<POCO>(p => p.Title),
Value = "my_title"
};
Also I am not sure if there is any difference between, creating a TermQuery using QueryContainerDescriptor and the above method?
QueryContainer qcd = new QueryContainerDescriptor<POCO>().
Term(r => r.Field(f => f.Title).Value("my_title"));
QueryBase is the base type for all concrete query implementations
QueryContainer is a container for a query. It is used in places where a query is expected.
QueryContainerDescriptor<T> is a type for building a QueryContainer using a builder / fluent interface pattern.
NEST supports both an Object Initializer syntax where requests can be composed through instantiating types and composing an object graph by assigning types to properties, and also a Fluent API syntax, where requests can be composed using Lambda expressions and a fluent interface pattern. All *Descriptor types within NEST are builders for the Fluent API syntax. Use whichever syntax you prefer, or mix and match as you see fit :)
You might be thinking, why do we need QueryContainer, why not just use QueryBase? Well, within the JSON representation, a query JSON object is keyed against the name of the query as a property of an outer containing JSON object i.e.
{
"query": { // <-- start of outer containing JSON object
"term": { // <-- start of JSON query object
"field": {
"value": "value"
}
}
}
}
Relating back to C# types, QueryBase will be serialized to the query JSON object and QueryContainer will be the outer containing JSON object. To make it easier to compose queries, there are implicit conversions from QueryBase to QueryContainer, so often you just need to instantiate a derived QueryBase implementation and assign it to a property of type QueryContainer
var client = new ElasticClient();
var termQuery = new TermQuery
{
Field = "field",
Value = "value"
};
var searchRequest = new SearchRequest<MyDocument>
{
Query = termQuery // <-- Query property is of type QueryContainer
};
var searchResponse = client.Search<MyDocument>(searchRequest);
With QueryContainerDescriptor<T>, you often don't need to instantiate an instance outside of the client call, as an instance will be instantiated within the call. Here's the same request with the Fluent API
client.Search<MyDocument>(s => s
.Query(q => q
.Term("field", "value")
)
);

web api - list all data types on a class

I'm trying to list all the data types on a class and after give the information to a client
i know that i have to use the GetType. So here is what i have at the moment
var variables = typeof(MockClass).GetType()
.Select(field => field.Name) //error: 'Type' does not contain a definition for select
.ToList();
I'm trying to enter inside the class, use a query to select all the variables name and try to get their data type.. Any ideas?
Try this
var type = typeof(MockClass);
var nestedTypes = new List<Type>();
var typeNames = new List<string>();
var propertiesNames = new List<string>();
foreach(var p in type.GetProperties())
{
var t = p.PropertyType;
nestedTypes.Add(t);
typeNames.Add(t.Name);
propertiesNames.Add(p.Name);
}

Bulk Update on ElasticSearch using NEST

I am trying to replacing the documents on ES using NEST. I am seeing the following options are available.
Option #1:
var documents = new List<dynamic>();
`var blkOperations = documents.Select(doc => new BulkIndexOperation<T>`(doc)).Cast<IBulkOperation>().ToList();
var blkRequest = new BulkRequest()
{
Refresh = true,
Index = indexName,
Type = typeName,
Consistency = Consistency.One,
Operations = blkOperations
};
var response1 = _client.Raw.BulkAsync<T>(blkRequest);
Option #2:
var descriptor = new BulkDescriptor();
foreach (var eachDoc in document)
{
var doc = eachDoc;
descriptor.Index<T>(i => i
.Index(indexName)
.Type(typeName)
.Document(doc));
}
var response = await _client.Raw.BulkAsync<T>(descriptor);
So can anyone tell me which one is better or any other option to do bulk updates or deletes using NEST?
You are passing the bulk request to the ElasticsearchClient i.e. ElasticClient.Raw, when you should be passing it to ElasticClient.BulkAsync() or ElasticClient.Bulk() which can accept a bulk request type.
Using BulkRequest or BulkDescriptor are two different approaches that are offered by NEST for writing queries; the former uses an Object Initializer Syntax for building up a request object while the latter is used within the Fluent API to build a request using lambda expressions.
In your example, BulkDescriptor is used outside of the context of the fluent API, but both BulkRequest and BulkDescriptor implement IBulkRequest so can be passed to ElasticClient.Bulk(IBulkRequest).
As for which to use, in this case it doesn't matter so whichever you prefer.

Insert data to ElasticSearch using NEST API

I am trying to insert\bulk insert data to Elastic using NEST API.
Can someone provide me the example using NEST?
Thanks,
Sameer
NEST documantation contains examples how to do this e.g.:
var descriptor = new BulkDescriptor();
foreach (var i in Enumerable.Range(0, 1000))
{
descriptor.Index<ElasticSearchProject>(op => op
.Document(new ElasticSearchProject {Id = i})
);
}
var result = client.Bulk(descriptor);
Also you can use IndexMany which is quite useful
var documents= new List<ElasticSearchProject> {...};
client.IndexMany(documents);
Good luck.

Resources