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.
Related
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"
]
I am new to mongodb , I have two collections like this :
1st collection name is A
{
"_id": "1234",
"versions": [{
"owner_id": ObjectId("100000"),
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": ObjectId("100001"),
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
]}
2nd Collection name is B
{ "_id": ObjectId("100000"), "email": "abc#xyz.com" } { "_id": ObjectId("100001"), "email": "bbc#xyz.com"}
Expected output is :
{
"_id": "1234",
"versions":[{
"owner_id": "abc#xyz.com",
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": "bbc#xyz.com",
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
] }
I used mongo $lookup but I am not getting required output
Please help.
Thank You!!!
You need to $unwind versions, $lookup with another collection on foreignField, $project to take the first element from the match array, $group to get back in original document format
collection a
> db.a.find()
{ "_id" : "1234", "versions" : [ { "owner_id" : "100000" }, { "owner_id" : "100001" }, { "owner_id" : "100001" } ] }
collection b
> db.b.find()
{ "_id" : "100000", "email" : "abc#xyz.com" }
{ "_id" : "100001", "email" : "bbc#xyz.com" }
aggregate pipeline
> db.a.aggregate(
[
{$unwind:"$versions"},
{$lookup : {from : "b", "localField":"versions.owner_id", "foreignField":"_id", as :"out"}},
{$project : {"_id":1, "versions.owner_id":{$arrayElemAt:["$out.email",0]}}},
{$group:{_id:"$_id", versions : {$push : "$versions"}}}
]
).pretty()
output
{
"_id" : "1234",
"versions" : [
{
"owner_id" : "abc#xyz.com"
},
{
"owner_id" : "bbc#xyz.com"
},
{
"owner_id" : "bbc#xyz.com"
}
]
}
I am new to MongoDB, I have two collections like this :
1st collection name is a
db.a.find()
{
"_id": "1234",
"versions": [{
"owner_id": ObjectId("100000"),
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": ObjectId("100001"),
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
]}
2nd Collection name is b
db.b.find()
{
"_id": ObjectId("100000"),
"email": "abc#xyz.com"
} {
"_id": ObjectId("100001"),
"email": "bbc#xyz.com"
}
Expected output is:
{
"_id": "1234",
"versions":[{
"owner_id": "abc#xyz.com",
"versions": 1,
"type" : "info",
"items" : ["item1","item3","item7"]
},
{
"owner_id": "bbc#xyz.com",
"versions": 2,
"type" : "bug",
"OS": "Ubuntu",
"Dependencies" : "Trim",
"items" : ["item1","item7"]
}
] }
Requirement: fields inside each document of versions are not fixed,
Example : versions[0] have 4 key-value pair and versions[1] have 6 key-value pair.
so I am looking a query which can replace owner_id with email keeping all other filed in output.
I tried :
db.a.aggregate(
[
{$unwind:"$versions"},
{$lookup : {from : "b", "localField":"versions.owner_id", "foreignField":"_id", as :"out"}},
{$project : {"_id":1, "versions.owner_id":{$arrayElemAt:["$out.email",0]}}},
{$group:{_id:"$_id", versions : {$push : "$versions"}}}
]
).pretty()
Please help.
Thank You!!!
Instead of $project pipeline stage use $addFields.
Example:
db.a.aggregate([
{ $unwind: "$versions" },
{
$lookup: {
from: "b",
localField: "versions.owner_id",
foreignField: "_id",
as: "out"
}
},
{
$addFields: {
"versions.owner_id": { $arrayElemAt: ["$out.email",0] }
}
},
{ $group: { _id: "$_id", versions: { $push: "$versions" } } }
]).pretty()
I am having trouble with the syntax (SyntaxError: Unexpected token ILLEGAL) in MongoDB. This command was copied directly from a MongoDB instruction PDF and I cannot find out what is wrong.
Also I don't know if it is relevant but I am using Codeanywhere with a MEAN stack.
db.restaurants.insert(
{
"address" : {
"street" : "2 Avenue",
"zipcode" : "10075",
"building" : "1480",
"coord" : [ 73.9557413, 40.7720266 ],
},
"borough" : "Manhattan",
"cuisine" : "Italian",
"grades" : [
{
"date" : ISODate("20141001T00:00:00Z"),
"grade" : "A",
"score" : 11
},
{
"date" : ISODate("20140116T00:00:00Z"),
"grade" : "B",
"score" : 17
}
],
"name" : "Vella",
"restaurant_id" : "41704620"
}
)
Try to replace:
"coord" : [ 73.9557413, 40.7720266 ],
with:
"coord" : [ 73.9557413, 40.7720266 ]
The comma at the end of subdocument is extra.
By the way, the JSON standard allows only double quoted string as property key, thus, try also this variant:
"coord" : [ "73.9557413", "40.7720266" ]
I checked your entire JSON-document with a JSON validator, here is a valid version:
{
"address": {
"street": "2 Avenue",
"zipcode": "10075",
"building": "1480",
"coord": ["73.9557413", "40.7720266"]
},
"borough": "Manhattan",
"cuisine": "Italian",
"grades": [{
"date": "20141001T00:00:00Z",
"grade": "A",
"score": 11
}, {
"date": "20140116T00:00:00Z",
"grade": "B",
"score": 17
}],
"name": "Vella",
"restaurant_id": "41704620"
}
I am trying to figure out how oneOf works by building a schema which validates two different object types. For example a person (firstname, lastname, sport) and vehicles (type, cost).
Here are some sample objects:
{"firstName":"John", "lastName":"Doe", "sport": "football"}
{"vehicle":"car", "price":20000}
The question is what have I done wrongly and how can I fix it. Here is the schema:
{
"description": "schema validating people and vehicles",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [ "oneOf" ],
"properties": { "oneOf": [
{
"firstName": {"type": "string"},
"lastName": {"type": "string"},
"sport": {"type": "string"}
},
{
"vehicle": {"type": "string"},
"price":{"type": "integer"}
}
]
}
}
When I try to validate it in this parser:
https://json-schema-validator.herokuapp.com/
I get the following error:
[ {
"level" : "fatal",
"message" : "invalid JSON Schema, cannot continue\nSyntax errors:\n[ {\n \"level\" : \"error\",\n \"schema\" : {\n \"loadingURI\" : \"#\",\n \"pointer\" : \"/properties/oneOf\"\n },\n \"domain\" : \"syntax\",\n \"message\" : \"JSON value is of type array, not a JSON Schema (expected an object)\",\n \"found\" : \"array\"\n} ]",
"info" : "other messages follow (if any)"
}, {
"level" : "error",
"schema" : {
"loadingURI" : "#",
"pointer" : "/properties/oneOf"
},
"domain" : "syntax",
"message" : "JSON value is of type array, not a JSON Schema (expected an object)",
"found" : "array"
} ]
Try this:
{
"description" : "schema validating people and vehicles",
"type" : "object",
"oneOf" : [
{
"type" : "object",
"properties" : {
"firstName" : {
"type" : "string"
},
"lastName" : {
"type" : "string"
},
"sport" : {
"type" : "string"
}
}
},
{
"type" : "object",
"properties" : {
"vehicle" : {
"type" : "string"
},
"price" : {
"type" : "integer"
}
},
"additionalProperties":false
}
]
}
oneOf need to be used inside a schema to work.
Inside properties, it's like another property called "oneOf" without the effect you want.