I'm new to JSON Path.
Note: I have already checked over some questions on SO, it's not helping me with my issue.
I have an example JSON given below :
{
"phoneNumbers": [
{
"type": "iPhone",
"number": "0123-4567-8888"
},
{
"type": "iPhone",
"number": "0123-4567-8910"
},
{
"type": "Samsung",
"number": "0123-4567-8912"
}
]
}
Now, I have created JSON Path query which will bring all the json objects having the type as 'iPhone' :
$.phoneNumbers[?(#.type == 'iPhone')]
Output :
[
{
"type": "iPhone",
"number": "0123-4567-8888"
},
{
"type": "iPhone",
"number": "0123-4567-8910"
}
]
After this, I want to extract element from the first index. That's where I got stuck.
I tried this query :
$.phoneNumbers[?(#.type == 'iPhone')][0]
But this query is not returning any results. What is the wrong with this query ?
Hope this helps
Filter expression return array can not use [index] get item inside
I'm not quite familiar with json path but on which platform do you run it?
Edit:
You need to define a key to the array because phoneNumbers is undefined
{
"phoneNumbers": [
{
"type": "iPhone",
"number": "0123-4567-8888",
},
{
"type": "iPhone",
"number": "0123-4567-8910",
},
],
};
Then the default query jsonpath.com
$.phoneNumbers[:1].type
outputs:
[
"iPhone"
]
Related
I have a requirement to roll a collection of nodes that uses the current node name (within the collection) and for the value take each child nodes value (single node) into a string array, then use the parents key as the key.
Given.
{
"client": {
"addresses": [
{
"id": "27ef465ef60d2705",
"type": "RegisteredOfficeAddress"
},
{
"id": "b7affb035be3f984",
"type": "PlaceOfBusiness"
},
{
"id": "a8a3bef166141206",
"type": "EmailAddress"
}
],
"links": [
{
"id": "29a9de859e70799e",
"type": "Director",
"name": "Bob the Builder"
},
{
"id": "22493ad4c4fd8ac5",
"type": "Secretary",
"name": "Jennifer"
}
],
"Names": [
{
"id": "53977967eadfffcd",
"type": "EntityName",
"name": "Banjo"
}
]
}
}
from this the output needs to be
{
"client": {
"addresses": [
"RegisteredOfficeAddress",
"PlaceOfBusiness",
"EmailAddress"
],
"links": [
"Director",
"Secretary"
],
"Names": [
"EntityName"
]
}
}
What is the best way to achieve this? Any pointers to what/how to do this would be greatly appreciated.
Ron.
You can iterate over entries of your client object first with the help of the $each function, then get types for each of them, and combine via $merge:
{
"client": client
~> $each(function($list, $key) {{ $key: $list.type }})
~> $merge
}
Live playground: https://stedi.link/OpuRdE9
I am working with a specific API that returns a JSON that looks like the below sample.
I want to get both values that contain the #text and #attr but I get error messages in typescript when I try to get the values.
try using,
album[0]["#attr"]
album[0]["artist"]["#text"]
Hey for JSON you can use get details by its attribute name in it and it's the same for all-weather it starts with # or # it will be the same.
See below code to get the value of your specified key:
Sample JSON:
{
"weeklyalbumchart": {
"album": [
{
"artist": {
"mbid": "data",
"#text": "Flying Lotus"
},
"mbid": "data",
"url": "",
"name": "",
"#attr": {
"rank": "1"
},
"playcount": "21"
},
{
"artist": {
"mbid": "data",
"#text": "Flying Lotus"
},
"mbid": "data",
"url": "",
"name": "",
"#attr": {
"rank": "1"
},
"playcount": "21"
}
]
}
}
Read JSON:
#attr ===> json["weeklyalbumchart"]["album"][0]["#attr"]
#text ===> json["weeklyalbumchart"]["album"][0]["artist"]["#text"]
Hope this will help you to understand it.
I am attempting get a value based on the key containing # symbol fails using JSONPath.
Cause: Since # is the current object/element, json does not return the value.
Sample 1:
{
"firstName": "John",
"lastName" : "doe",
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}
This works: $.phoneNumbers[1].type
This works: $.phoneNumbers[?(#.type=="iPhone")].type
Sample2:
{
"firstName": "John",
"lastName" : "doe",
"phoneNumbers": [
{
"#type" : "iPhone",
"number": "0123-4567-8888"
},
{
"#type" : "home",
"number": "0123-4567-8910"
}
]
}
This works: $.phoneNumbers[1].type
This does not work: $.phoneNumbers[?(#.#type=="iPhone")].type
Any advice for dealing with keys and values containing # characters?
It depends which jsonpath implementation you are using.
If you are using JsonPath-Plus then you can try something like:
$.phoneNumbers[?(#['#type'] == "iPhone")]
You can evaluate jsonpath online here which is based on JsonPath-Plus.
I've seen this other question but it's not quite the same, and I feel like my issue is simpler, but just isn't working.
My data would look like this:
[
{ "loc": "a value 1", "toll" : null, "message" : "message is sometimes null"},
{ "loc": "a value 2", "toll" : "toll is sometimes null", "message" : null}
]
I'm wanting to use AJV for JSON validation in a Node.js project and I've tried several schemas to try to describe my data, but I always get this as the error:
[ { keyword: 'type',
dataPath: '',
schemaPath: '#/type',
params: { type: 'array' },
message: 'should be array' } ]
The schema I've tried looks like this:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"loc": {
"type": "string"
},
"toll": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"loc"
]
}
}
I've also tried to generate the schema using this online tool but that also doesn't work, and to verify that that should output the correct result, I've tried validating that output against jsonschemavalidator.net, but that also gives me a similar error:
Found 1 error(s)
Message:
Invalid type. Expected Array but got Object.
Schema path:
#/type
You have defined your schema correctly, except that it doesn't match the data you say you are validating. If you change the property names to match the schema, you still have one issue. If you want to allow "toll" and "message" to be null, you can do the following.
{
"type": "array",
"items": {
"type": "object",
"properties": {
"loc": {
"type": "string"
},
"toll": {
"type": ["string", "null"]
},
"message": {
"type": ["string", "null"]
}
},
"required": [
"loc"
]
}
}
However, that isn't related to the error message you are getting. That message means that data you are validating is not an array. The example data you posted should not result in this error. Are you running the validator on some data other than what is posted in the question?
I have some problem with facets tokenize tags with spaces.
I have the following mappings:
curl -XPOST "http://localhost:9200/pictures" -d '
{
"mappings" : {
"pictures" : {
"properties" : {
"id": { "type": "string" },
"description": {"type": "string", "index": "not_analyzed"},
"featured": { "type": "boolean" },
"categories": { "type": "string", "index": "not_analyzed" },
"tags": { "type": "string", "index": "not_analyzed", "analyzer": "keyword" },
"created_at": { "type": "double" }
}
}
}
}'
And My Data is:
curl -X POST "http://localhost:9200/pictures/picture" -d '{
"picture": {
"id": "4defe0ecf02a8724b8000047",
"title": "Victoria Secret PhotoShoot",
"description": "From France and Italy",
"featured": true,
"categories": [
"Fashion",
"Girls",
],
"tags": [
"girl",
"photoshoot",
"supermodel",
"Victoria Secret"
],
"created_at": 1405784416.04672
}
}'
And My Query is:
curl -X POST "http://localhost:9200/pictures/_search?pretty=true" -d '
{
"query": {
"text": {
"tags": {
"query": "Victoria Secret"
}
}
},
"facets": {
"tags": {
"terms": {
"field": "tags"
}
}
}
}'
The Output result is:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 0,
"max_score" : null,
"hits" : [ ]
},
"facets" : {
"tags" : {
"_type" : "terms",
"missing" : 0,
"total" : 0,
"other" : 0,
"terms" : [ ]
}
}
}
Now, I got total 0 in facets and total: 0 in hits
Any Idea Why its not working?
I know that when I remove the keyword analyzer from tags and make it "not_analyzed" then I get result.
But there is still a problem of case sensitive.
If I run same above query by removing the keyword analyzer then I get the result which is:
facets: {
tags: {
_type: terms
missing: 0
total: 12
other: 0
terms: [
{
term: photoshoot
count: 1
}
{
term: girl
count: 1
}
{
term: Victoria Secret
count: 1
}
{
term: supermodel
count: 1
}
]
}
}
Here Victoria Secret is case sensitive in "not_analyzed" but it takes space in count, but when I query with lowercase as "victoria secret" it doesn't give any results.
Any suggestions??
Thanks,
Suraj
The first examples are not totally clear to me. If you use the KeywordAnalyzer it means that the field will be indexed as it is, but then it makes much more sense to just not analyze the field at all, which is the same. The mapping you posted contains both
"index": "not_analyzed", "analyzer": "keyword"
which doesn't make a lot of sense. If you are not analyzing the field why would select an analyzer for it?
Apart from this, of course if you don't analyze the field the tag Victoria Secret will be indexed as it is, thus the query victoria secret won't match. If you want it to be case-insensitive you need to define a custom analyzer which uses the KeyworkTokenizer, since you don't want to tokenize it and the LowercaseTokenFilter. You can define a custom analyzer through the index settings analysis section and then use it in your mapping. But that way the facet would be always lowercase, which is something that you don't like I guess. That's why it's better to define a multi field and index the field using two different text analysis, one for the facet and one for search.
You can create the index like this:
curl -XPOST "http://localhost:9200/pictures" -d '{
"settings" : {
"analysis" : {
"analyzer" : {
"lowercase_analyzer" : {
"type" : "custom",
"tokenizer" : "keyword",
"filter" : [ "lowercase"]
}
}
}
},
"mappings" : {
"pictures" : {
"properties" : {
"id": { "type": "string" },
"description": {"type": "string", "index": "not_analyzed"},
"featured": { "type": "boolean" },
"categories": { "type": "string", "index": "not_analyzed" },
"tags" : {
"type" : "multi_field",
"fields" : {
"tags": { "type": "string", "analyzer": "lowercase_analyzer" },
"facet": {"type": "string", "index": "not_analyzed"},
}
},
"created_at": { "type": "double" }
}
}
}
}'
Then the custom lowercase_analyzer will be applied by default to the text query too when you search on that field, so that you can either search for Victoria Secret or victoria secret and get the result back. You need to change the facet part and make the facet on the new tags.facet field, which is not analyzed.
Furthermore, you might want to have a look at the match query since the text query has been deprecated with the latest elasticsearch version (0.19.9).
I think this make some sense to my answer
https://gist.github.com/2688072