Need Explanation on ElasticSearch Filters Aggregation - json

I'm trying to understand the syntax of Filters Aggregations in ElasticSearch, and I'm stumped. The example given in the documentation is this:
{
"aggs" : {
"messages" : {
"filters" : {
"filters" : {
"errors" : { "term" : { "body" : "error" }},
"warnings" : { "term" : { "body" : "warning" }}
}
},
"aggs" : {
"monthly" : {
"histogram" : {
"field" : "timestamp",
"interval" : "1M"
}
}
}
}
}
}
I understand the following:
"aggs" defines the aggregations blocks (it's a shortcut for "aggregations"). There's actually nested aggregations in the example, as can be seen.
"messages" is the user-defined name of the aggregation block.
"errors" and "warnings" are user-defined names of the filters used to create the "buckets" for the aggregation. They drop items with "body" equal to "error" and "warning" respectively ("term" matching).
What I don't understand is why "filters" appears twice, nested inside of itself. Per the general aggregations syntax:
"aggregations" : {
"<aggregation_name>" : {
"<aggregation_type>" : {
<aggregation_body>
}
[,"aggregations" : { [<sub_aggregation>]+ } ]?
}
[,"<aggregation_name_2>" : { ... } ]*
}
"aggs" is short for "aggregations"
"messages" is my "<aggregation name"
"filters" is the ""
What's the second "filters" element doing? And where is it documented that "filters" has to be self-nested; it doesn't seem to be the case for any of the other aggregations I'm learning.

I understand how you feel, been there, too :-)
In the filters aggregation, the first filters occurrence is the aggregation_type and the second is part of the aggregation_bodyof the filters aggregation and is the only valid key that this aggregation supports.
The second filters occurrence could have been called anything else (filter_list, list, etc) to denote that it contains the list of filters for that aggregation, but the ES folks picked filters which happen to also be the same name as the name of the aggregation itself.
So it goes like this:
{
"aggs" : { <--- key word to declare aggregations
"messages" : { <--- custom name for the aggregation that follows
"filters" : { <--- aggregation_type
"filters" : { <--- first (and only) key of the aggregation_body
"errors" : { "term" : { "body" : "error" }},
"warnings" : { "term" : { "body" : "warning" }}
}
},
"aggs" : {
"monthly" : {
"histogram" : {
"field" : "timestamp",
"interval" : "1M"
}
}
}
}
}
}

Related

JSON Path - How to find the root elements based on child elements?

I have a JSON object, and I'm trying to find the root elements under it. Can someone please help me to figure this out?
{
"store" : {
"10162021" : {
"id" : 812340,
"properties" : {
"server" : "server1.example.org",
"serverip" : "",
}
},
"10162022" : {
"properties" : {
"serverip" : "127.0.0.1",
"server" : "server2.example.org",
},
"id" : 859480
}
}
}
I need to extract the root elements 10162022, 10162021 based on the server name.
I have tried to use syntax like below, but it was not successful
$..*..[?(#.server == server2.example.org)]
I will appreciate any suggestions.
It's not clear whether you want to return the keys "10162022", etc, or the values, like:
{
"properties" : {
"serverip" : "127.0.0.1",
"server" : "server2.example.org"
},
"id" : 859480
}
If you want to return values, the following JSONPath should work:
$.store[?( #.properties.server=="server2.example.org" )]
If you want to return keys, I'm not entirely sure that's possible. JSONPath isn't really designed to find keys, but values.
If you need the keys, I would suggest pre-processing the structure to stash the keys into objects as values, like this:
{
"store" : {
"10162021" : {
"__key" : "10162021",
"id" : 812340,
"properties" : {
"server" : "server1.example.org",
"serverip" : ""
}
},
"10162022" : {
"__key" : "10162022",
"properties" : {
"serverip" : "127.0.0.1",
"server" : "server2.example.org"
},
"id" : 859480
}
}
}
Then use this JSONPath:
$.store[?( #.properties.server=="server2.example.org" )].__key

Json schema validation : required attributes based on attributes from different object in same json

I have a requirement where i need to define attribute in one object as required based on value of attribute in another object.
e.g
{
"if" : {
"properties" : {
"Status" : {
"const" : "CANCELLED"
}
},
"required" : [
"Status"
]
},
"then" : {
"required" : [
"Reason"
]
}
}
above condition works. However below e.g doesn't work
{
"if" : {
"properties" : {
"#/Details/HasAgreement" : {
"const" : true
}
},
"required" : [
"#/Details/HasAgreement"
]
},
"then" : {
"required" : [
"#/Contract/EffectiveDate"
]
}
}
I'm guessing that the way how I'm referring attributes from different objects in same json is wrong. what is the right way?
Thanks,
Madhu

How to use .indexOn for dynamic keys in firebase?

I have a DB in Firebase with this structure:
{
"chats" : {
"-L-hPbTK51XFwjNPjz3X" : {
"lastMessage" : "Hello!",
"timestamp" : 1512590440336,
"title" : "chat 1",
"users" : {
"Ol0XhKBksFcrYmF4MzS3vbODvT83" : true
}
}
},
"messages" : {
"-L-hPbTK51XFwjNPjz3X" : {
"-L-szWDIKX2SQl4YZFw9" : {
"message" : "Hello!",
"timestamp" : 1512784663447,
"userId" : "Ol0XhKBksFcrYmF4MzS3vbODvT83"
}
}
},
"users" : {
"Ol0XhKBksFcrYmF4MzS3vbODvT83" : {
"chats" : {
"-L-hPbTK51XFwjNPjz3X" : true
},
"email" : "mm#gmail.com",
"name" : "mm"
}
}
}
My code:
Database.database().reference().child("chats")
.queryOrdered(‌​byChild: "users/(userId)").queryEqual(toValue: true).observe(.value, with: { snapshot in .... }
When I try to get chat members or user chats, It shows this warnings:
Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "chats/-L-hPbTK51XFwjNPjz3X" at /users to your security rules for better performance.
Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding ".indexOn": "users/Ol0XhKBksFcrYmF4MzS3vbODvT83" at /chats to your security rules for better performance.
I found lots of solutions but anything works fine for me. I want to define IndexOn rules in my DB, Can you help me?

Filtering JSONPath with given string value

If I have a JSON like so:
{
"data": [
{
"service" : { "id" : 1 }
},
{
"service" : { "id" : 2 }
},
{
"service" : {}
}
]
}
This query works:
$..service[?(#.id==2)]
And gives expected result:
[
{
"id" : 2
}
]
However, if I had strings as id's:
{
"data": [
{
"service" : { "id" : "a" }
},
{
"service" : { "id" : "b" }
},
{
"service" : {}
}
]
}
Running similar query:
$..service[?(#.id == "a")]
Gives no results (empty array).
I am using this evaluator.
I was looking at docs here but could not find anything to point me in the right direction... Any help if someone knows how to write such query? Thanks :)
without " works
$..service[?(#.id == b)]
give this result
[
{
"id" : "b"
}
]

How to map UML composition cardinality to JSON schema?

How to specify that a property of type object can appear only 1 time (i think this is default), N times, or any times? Or even not at all.
The question is, how to translate the standard UML composition cardinality information (min..max) to JSON Schema in case of properties of type 'object'?
"A" : {
"type" : "object",
"properties" : {
"B" : {
"type" : "object"
},
},
}
based on this schema, A may contain exactly one B, however I need to be able to specify:
- if it may contain none
- it may contain more (n)
- it may contain any
Thanks:
Endre
If you want to show the meta-definition info in JSon, a natural solution would be to add a "MultiplicityElement" and "AggregationKind" attributes (like in the UML metamodel):
{
"A": {
"type": "object",
"properties": [
{
"B": {
"type": "object",
"AggregationKind": "composite",
"MultiplicityElement": {
"lower": 0,
"upper": "n"
}
}
}
]
}
}
You might want to use "class" instead of "object" in this case, since you actually define your class structure. Alternative values for AggregationKind are "shared" (for aggregation) or "none".
Note that I put "properties" in a [] brackets, to indicate that there can be further properties added.
UPDATE (after the 1st comment)
First of all - the JSon is perfectly valid. Take a lok at this site: http://jsonlint.com/ I don't have time to investigate the reason of the fault on the one proposed by you, I suspect it has to do with the schema.
And more important - be careful here, I think you are mixing meta-model with model-information. I suspected this during my original answer and now you practically confirmed it.
The question is do you intend to show description of a class model (meta-model level) or description of a object model (model level).
If this is a class model description: change type to "class" and describe each class only once
If this is an object model: add a tag "class" to indicate the base class, use "values" instead of the "properties", use "property" instead of "type" to indicate the corresponding properties, remove AggregationKind and MultiplicityElement.
Or clarify your intention :)
Schema:
{
"type" : "object",
"properties" : {
"A" : {
"type" : "object",
"properties" : {
"B" : {
"type" : "array",
"minItems" : 1,
"maxItems" : 2
}
},
"required" : [ "B" ]
}
}
}
Valid instance:
{
"A": {
"B" : [ 1 ]
}
}
Another valid instance:
{
"A": {
"B" : [ 1, 2 ]
}
}
A not valid instance:
{
"A": {
}
}
Another not valid instance:
{
"A": {
"B" : []
}
}
Yet another not valid instance:
{
"A": {
"B" : [ 1, 2, 3]
}
}