I have a json document which has a structure as is displayed below:
{
"125": {
"name": "sample name one",
"age" : 22,
},
"126": {
"name": "sample name two",
"age" : 27,
},
"127": {
"name": "sample name three",
"age" : 21,
}
}
I want to return the object represented by 125, i.e. the following object :
{
"name": "sample name one",
"age" : 22,
}
I have tried the following query from the console, but I cannot get the result I need:
db.persons.find({"125": {$exists: true}}).
I would like to know how to query the database to return the data that I need. Thank you for any help.
db.persons.find({"125": {$exists: true}})
would return whole document, that has "125" key, not only the "125" key.
If You need to return only the "125", You should use projection, passing it as second argument to find:
db.persons.find({"125": {$exists: true}}, {"125": 1})
then You will get documents containing "125" key, without any other keys (except _id of that document)
To omit _id of document, You need to use:
db.persons.find({"125": {$exists: true}}, {"125": 1, _id: 0})
EDIT:
Did You consider using array for those subdocuments with repeating schema? It would be more natural, idiomatic, and also give You some additional possibilities.
In mongo search by JSON key / field / name, use $exists operator
db.things.find( { '125' : { $exists : true } } );
Related
I have a JOSN some thing like this
{
"Room" :{
"Book" :
{
"name" : "abc"
},
"Book1":
{
"name" : "xyz"
},
"Book3":
{
"name" : "abc123"
},
"Tv" :
{
"name" : "zyc"
},
"audio":
{
"name" :"sound ++"
}
}
}
From this JSON I want to filter out all book elements("book","book1","book2") using JSONPATH
As I got to know in in JSONPATH we do not have any "Like" type syntax , but we can do that by using regex.
I tried with this
$.Room[?(/^.*book.*$/i.test(#.Room))]
But this expression return nothing from the JSON.
Can any one help me out in this...
Maybe this link will be helpful for you . Check the table
$..book[?(#.author =~ /.*Tolkien/i)]. This expression brings All books whose author name ends with Tolkien (case-insensitive) --> Modify it for yours
{
"responseCode": "200",
"data": {
"sequence": 1,
"used": true,
"sensingTags": [
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
]
}
}
My goal is get updatedOn value from this json using jsonPath like this
1587557350251
i thought below jsonPath will work but it extract only empty list.
$..sensingTags[?(#.code == 'LED')][0].updatedOn
And i want to know how to extract value like below
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
Not like this one.
[
{
"code" : "LED",
"value" : 1,
"updatedOn" : 1587557350251
}
]
As per Getting a single value from a JSON object using JSONPath, JsonPath will always return an array (or a false) at that point...
Best you can do is process it as an array of updatedOn and simply always grab the first value.
$..sensingTags[?(#.code == 'LED')].updatedOn
I'd like to select all elements with a certain match in the name of the property.
For example, all the properties whose name starts with 'pass' from this json:
{
"firstName": "John",
"lastName" : "doe",
"age" : 50,
"password" : "1234",
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888",
"password": "abcd"
},
{
"type" : "home",
"number": "0123-4567-8910",
"password": "fghi"
}
]
}
Would result something like this:
[
"1234",
"abcd",
"fghi"
]
I don't want filter by values, only by property names. Is it possible using jsonpath?
I'm using the method SelectTokens(string path) of Newtonsoft.Json.Linq
No, JSONPath defines expressions to traverse through a JSON document to reach to a subset of the JSON. It cannot be used when you don't know the exact property names.
In your case you need property values whose name starts with a specific keyword. For that, you need to traverse the whole JSON text and look for the property names which start with pass having a string type
var passwordList = new List<string>();
using (var reader = new JsonTextReader(new StringReader(jsonText)))
{
while (reader.Read())
{
if(reader.TokenType.ToString().Equals("PropertyName")
&& reader.ValueType.ToString().Equals("System.String")
&& reader.Value.ToString().StartsWith("pass"))
{
reader.Read();
passwordList.Add(reader.Value.ToString());
}
}
passwordList.ForEach(i => Console.Write("{0}\n", i));
}
From the below JSON data, I want to cut out the attributes object and keep only Name of the Account. Sample JSON
{
"Accounts":[
{
"attributes":{
"type":"Account",
"url":"/services/data/v41.0/sobjects/Account/001S0000008mgjpIAA"
},
"Name":"Name+Test#Reseller"
},
{
"attributes":{
"type":"Account",
"url":"/services/data/v41.0/sobjects/Account/001S000000m5gyuIAA"
},
"Name":"Test Reseller Myself"
}
]
}
After matching with REGEX and replacing with "". The JSON should look like,
{
"Accounts" : [{
"Name" : "Name+Test#Reseller"
}, {
"Name" : "Test Reseller Myself"
}]
}
Use map and return only name property value
obj.accounts = obj.accounts.map( s => {Name: s.Name } );
I found myself an answer. I constructed a two regex
1. "attributes" : {\w*\W*\d*\D*\d*.\d*\D*\w*"\w*
2. {.\s*\S*
I cannot find examples in the Elastic manual on nested objects on how to modify fields and nested objects of documents using RESTful commands in Kibana Sense. I am looking for something similar to Solrs atomic updates here, which allow to update specific fields of documents.
How do RESTful commands in Kibana Sense look like that accomplish this? The only related info in the manual I can find is on Partial Updates to Documents, but I do not know how this can be applied for this use case.
For example, straight from the Elastic docs:
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
}
PUT my_index/my_type/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
How can I delete an entry in the nested object, so that the document "1" looks like:
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
}
]
}
How can I add an entry in the nested object, so that the document "1" looks like:
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
},
{
"first" : "Peter",
"last" : "Parker"
}
]
}
You will have to use scripted updates unless you want to fetch all nested objects then add / remove items and re-index them all which is the previous answer proposed. However if you have a lot of nested documents you should be doing partial updates / additions and deletes. It is much quicker from data transfer and indexing point of view.
Here is a good article how to do scripted updates in general:
https://iridakos.com/programming/2019/05/02/add-update-delete-elasticsearch-nested-objects
Unless I misunderstand your ask, you just post the updated document version to the same document id each time you want.
To delete a nested document (or any field):
PUT my_index/my_type/1
{
"group" : "fans",
"user" : [
{
"first" : "Alice",
"last" : "White"
}
]
}
To add a user, add it to the list:
PUT my_index/my_type/1
{
"group" : "fans",
"user" : [
{
"first" : "Alice",
"last" : "White"
},
{
"first" : "Peter",
"last" : "Parker"
}
]
}
Note: Documents in elasticsearch are immutable. Making a change to a single field causes the entire document to be re-indexed. Nested documents are always re-indexed with the parent document so if you change a field in the parent the nested document is also re-indexed. This can be a performance issue if the nested documents are large and the parents have frequent changes.
For this specific use case, you must use a scripted update. In javascript the call will look something like:
const documentUpdateInstructions = {
index: "index-name",
id: "document-id",
body: {
script: {
lang: "painless",
source: `ctx._source.myNestedObject.removeIf(object -> object.username == params.username);`,
params: {
username: "my_username"
},
},
},
};
await client.update(documentUpdateInstructions);
This takes a document in the form of
document._source = {
...
"myNestedObject": [
{
"username": "my_username",
...
},
{
"username": "not_my_username",
...
}
]
}
and deletes the object inside myNestedObject who's username matches the username provided (in this case my_username). The resulting document will be:
document._source = {
...
"myNestedObject": [
{
"username": "not_my_username",
...
}
]
}