I am trying to replicate this DSL query in NEST. Basically a structured filter that will return all of the products that have the color red.
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "keywordFacets",
"query": {
"bool": {
"filter": [
{ "term": { "keywordFacets.name": "color" } },
{ "term": { "keywordFacets.value": "Red" } }
]
}
}
}
}
]
}
}
}
Here is the POCO with attribute mapping.
[ElasticsearchType]
public class Product
{
[Keyword]
public long ProductId { get; set; }
[Nested]
public List<KeywordFacet> KeywordFacets { get; set; }
// other properties...
}
[ElasticsearchType]
public class KeywordFacet
{
[Keyword]
public string Name { get; set; }
[Keyword]
public string Value { get; set; }
}
I can't figure out how to get the two terms inside the nested filter array. This is my failed attempt so far:
var searchRequest = new SearchDescriptor<Product>()
.Query(q => q
.Bool(b => b
.Filter(bf => bf
.Nested(nq => nq
.Path(nqp => nqp.KeywordFacets)
.Query(qq => qq
.Bool(bb => bb
.Filter(ff => ff
.Term(t => t
.Field(p => p.KeywordFacets.First().Name)
.Value("color")
.Field(p2 => p2.KeywordFacets.First().Value).Value("Red")))))))));
Here is some sample data that is returned when I run the DSL query in Postman:
{
"productId": 183150,
"keywordFacets": [
{
"name": "color",
"value": "Red"
},
{
"name": "color",
"value": "Blue"
},
{
"name": "color",
"value": "Grey"
}
]
}
Here's the proper syntax after fumbling around for a while.
var searchRequest = new SearchDescriptor<Product>()
.Query(q => q
.Bool(b => b
.Filter(bf => bf
.Nested(nq => nq
.Path(nqp => nqp.KeywordFacets)
.Query(qq => qq.Bool(bb => bb
.Filter(ff => ff
.Term(t => t
.Field(p => p.KeywordFacets[0].Name).Value("color"))))
&& qq.Bool(bb => bb
.Filter(ff => ff
.Term(t => t
.Field(p2 => p2.KeywordFacets[0].Value).Value("Red"))))
)
)
)
)
);
Related
I have a query like below
query {
heroes {
node {
name
}
endCursor
}
}
I am trying to understand how GraphQL can handle the error handling and return partial response. I looked at https://github.com/graphql/dataloader/issues/169 and tried to create a resolver like below;
{
Query: {
heroes: async (_) => {
const heroesData = await loadHeroesFromDataWarehouse();
return {
endCursor: heroesData.endCursor;
node: heroesData.map(h => h.name === 'hulk' ? new ApolloError('Hulk is too powerful') : h)
}
}
}
}
I was hoping it would resolve something like below;
{
"errors": [
{
"message": "Hulk is too powerful",
"path": [
"heroes", "1"
],
}
],
"data": {
"heroes": [
{
"name": "spiderman"
},
null,
{
"name": "ironman"
}
]
}
}
but it is completely failing making the heroes itself null like below;
{
"errors": [
{
"message": "Hulk is too powerful",
"path": [
"heroes"
],
}
],
"data": {
"heroes": null
}
}
How can I make resolver to return me the desired partial response?
Found the solution, basically we need a resolver to resolve the edge model itself;
{
Query: {
heroes: (_) => loadHeroesFromDataWarehouse()
},
HeroesEdge {
node: async (hero) => hero.name === 'hulk' ? new ApolloError('Hulk is too powerful') : hero
}
}
I'm using IConfiguration.GetSection to retrieve configuration information from a config file:
var loggingProviders = Config.GetSection( "Logging" ).Get<LoggingProviders>();
which works just fine, but I want to only retrieve entries that are enabled, so I want to do either of these:
var loggingProviders = Config.GetSection( "Logging" ).Get<LoggingProviders>().Where( x => x.Enabled == true );
var loggingProviders = Config.GetSection( "Logging" ).Where( x => x.Enabled == true ).Get<LoggingProviders>();
But I keep getting hitting a dead end, any advice would be appreciated!
If you want to use .Where,it needs to be a list,here is a demo:
public class LoggingProviders
{
public int Id { get; set; }
public bool Enabled { get; set; }
}
appsettings.json:
"Logging1": [
{
"Id": "1",
"Enabled": "true"
},
{
"Id": "2",
"Enabled": "true"
},
{
"Id": "3",
"Enabled": "false"
}
]
startup:
public IConfiguration Configuration { get; }
...
List<LoggingProviders> loggingProviders = Configuration.GetSection("Logging1").Get<List<LoggingProviders>>().Where(x => x.Enabled == true).ToList();
result:
If you don't get a list,and want to use .where,you can try to change it to list first.Here is a demo.
appsettings.json:
"Logging1":
{
"Id": "1",
"Enabled": "true"
},
startup:
public IConfiguration Configuration { get; }
...
List<LoggingProviders> l= new List<LoggingProviders>();
l.Add(Configuration.GetSection("Logging1").Get<LoggingProviders>());
List<LoggingProviders> loggingProviders = l.Where(x => x.Enabled == true).ToList();
result:
Create two indices in elasticsearch parent and child
PUT parent/car/sedan
{
"type": "sedan",
"details": {
"wheels": 4,
"doors": 4,
"seats": 5,
"fuel": "gasoline"
}
}
PUT child/toyota/corolla
{
"color": "white",
"type": "sedan",
"details": {
"wheels": 4,
"doors": 4,
"seats": 5,
"fuel": "gasoline"
}
}
SQL UPDATE by JOIN (the corresponding SQL version that we'll perform on elasticsearch using logstash)
update CHILD.doors = PARENT.doors
from PARENT, CHILD
where PARENT.type = CHILD.type
ELASTICSEARCH UPDATE by JOIN (execute logstash with the logstash.conf as mentioned below)
input {
elasticsearch {
docinfo => true
hosts => ["127.0.0.1:9200"]
user => "admin"
password => "pass"
index => "child"
query => '{ "query": { "match": { "type": "sedan" } } }'
}
}
filter {
mutate {
remove_field => ["message","#version","#timestamp"]
}
elasticsearch {
hosts => ["127.0.0.1:9200"]
user => "admin"
password => "pass"
index => "parent"
query => "type:sedan"
fields => { "details.doors" => "parent_doors"
"details.seats" => "parent_seats"
"type" => "parent_type"
}
}
prune {
whitelist_names => ["color","type", "details","parent_doors","parent_seats","parent_type"]
}
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["127.0.0.1:9200"]
user => "admin"
password => "pass"
index => "%{[#metadata][_index]}"
document_type => "%{[#metadata][_type]}"
document_id => "%{[#metadata][_id]}"
action => "update"
doc_as_upsert => true
script_lang => "painless"
script => "if ( ctx._source.type == '%{parent_type}' ) { ctx._source.details.doors = %{parent_doors} }"
}
}
This Works. If you have a better way of achieving the same, please do let us know.
I'm using NEST 2.0.2 to query ElasticSearch.
Really great API, thanks for the effort, but needs documentation update I think.
Anyways,
I want to serialize my request. I could not find any info, there are some stackoverflow questions but it's about older versions, and api changed.
I want to write a "terms query". But could not succeed.
The working sense DSL is below.
GET myindex/mytype/_search?search_type=count
{
"query": {
"bool": {
"must": [
{
"term": {
"field1": {
"value": 2
}
}
}
],
"must_not": [
{
"terms": {
"field2": [
16,
17,
18,
19
]
}
}
]
}
},
"aggs": {
"termsAggField2": {
"terms": {
"field": "field2",
"size": 20
},
"aggs": {
"sumAggField3": {
"sum": {
"field": "field3"
}
}
}
}
}
}
And the terms query code is below. DSL works in sense, but the query does not working. The "not in" does not filter the output.
List<QueryContainer> must_not = new List<QueryContainer>();
must_not.Add(Query<mytype>.Terms(trms => trms.Terms(new string[] { "16", "17", "18", "19" })));
var resultTermsSum = b1.ElasticClient.Search<mytype>(q=>q.SearchType(SearchType.Count)
.Query(q2 => q2.Bool(
b => b.MustNot(must_not.ToArray())
)
)
.Aggregations(a => a.Terms("termsAggField2", terms => terms.Field("field2").Size(20)
.Aggregations(a2 => a2.Sum("sumAggField3", sum => sum.Field("field3"))))));
ie why I want to see the serialized request and see my problem.
thanks.
regards.
Edit: It's now working with the following update. It'd be great if I could serialize ;)
List<QueryContainer> must_not = new List<QueryContainer>();
short [] valueCollection = new short[] { 16, 19, 99, 100 };
must_not.Add(Query<mytpe>.Terms(trms => trms.Field("field2").Terms(valueCollection)));
var resultTermsSum = b1.ElasticClient.Search<mytype>(q=>q.SearchType(SearchType.Count)
.Query(q2 => q2.Bool(
b => b.MustNot(must_not.ToArray())
)
)
.Aggregations(a => a.Terms("termsAggField2", terms => terms.Field("field2").Size(20)
.Aggregations(a2 => a2.Sum("sumAggField3", sum => sum.Field("field3"))))));
I am trying to create a function_score elasticsearch query using NEST (gauss function), and have a geo point object to pass as the 'origin', however the "Origin" method in NEST accepts only a string, a result elasticsearch can't parse the query.
How can I write the query in NEST so Elasticsearch can parse it correctly?
var originLoc = JsonConvert.SerializeObject(userLocation.GeoCenter);
var searchDesc = new SearchDescriptor<MyCustomType>().Query(q => q.FunctionScore(fs => fs.Functions(func => func.Gauss("geoCenter", gs => gs.Origin(originLoc).Offset("1km").Scale("500m").Decay(0.99)))));
NEST passes the code above to elasticsearch like this, which elasticsearch can't parse (origin is parsed as string).
"query": {
"function_score": {
"functions": [
{
"gauss": {
"geoCenter": {
"origin": "{\"lat\":29.745703,\"lon\":-95.740514}", //<-- string
"scale": "500m",
"offset": "1km",
"decay": 0.99
}
}
}
]
}
}
Below is the correct query that Elasticsearch can run (origin is parsed as geo point object)
"query": {
"function_score": {
"functions": [
{
"gauss": {
"geoCenter": {
"origin": { //<----- geo point serialized object
"lon": -95.740514,
"lat": 29.745703
},
"scale": "500m",
"offset": "1km",
"decay": 0.99
}
}
}
]
}
i have something like this in my code
.Query(f => f
.FunctionScore(fs => fs
.BoostMode(FunctionBoostMode.Sum)
.Functions(ff => ff
.Linear("location", d => d.Origin(origin).Scale("8km").Decay(0.33))
)
)
)
Where origin -> var origin = object.latitude + "," + object.longitude;