How to search a nested object using zq? - filtering

Given this input in a file called plants.json
{
"flower": { "rose": 1 },
"tree": { "spruce": 1, "oak": 2, "oaky": 3 }
}
Filter it with zq so that it looks like this:
{
"flower": { "rose": 1 },
"tree": { "oak": 2, "oaky": 3 }
}
Effectively filtering a known and named nested object at the key tree to match oak.

Use zq's put operator (the :=) to redefine tree as a filtered search.
zq -f json 'tree:=unflatten((over tree | oak))' plants.json
{"flower":{"rose":1},"tree":{"oak":2,"oaky":3}}
This does a simple search on keys and values. If you want to match more precisely, you can use other functions where | oak is.
For example, if you have a document that also includes "soak":4
{
"flower": { "rose": 1 },
"tree": { "spruce": 1, "oak": 2, "oaky": 3, "soak": 4 }
}
Then this won't work because you'll get oak and oaky and soak. So use grep() and a regex for this case. This example demonstrates how to add the function grep to our previous command.
zq -f json 'tree:=unflatten((over tree | grep(/^oak/)))' plants.json
{"flower":{"rose":1},"tree":{"oak":2,"oaky":3}}
Note that tree:=unflatten(...) is the same as saying put tree:=unflatten(...) because put is an implied operator like oak is search oak. Some of the links on zq's doc site are currently broken but it is currently in the 2.6 language overview section.

Related

Update arrays in mongodb

We have to update the bulk values in different arrays.
Is there any way, we can update the values inside the different arrays at the same time ?
Currently, I have the path of the array, Old value and new values, I need to update lot of documents inside one collection - please do let me know if there is a way to do it in Mongodb 3.6 version.
For example:
Path in the collection Old Value New Value
orderDocument.customerOrderItems.customerOrderSubItems.productId 10001 10002
orderDocument.customerOrderItems.customerOrderSubItems.productName Upto 2 Tst/1 Tst Upto 33 Tst/22 Tst
Please share your document structure so we can provide more specific direction. Assuming your document looks like:
{
"orderDocument": {
"customerOrderItems": {
"customerOrderSubItems": [
{
"productId": 10004.0
}
]
}
}
}
Reach the array through a path where value needs to be changed then use the '$' and name of the property to be updated:
db.getCollection('Event').updateMany(
{
"orderDocument.customerOrderItems.customerOrderSubItems.productId": 10004
},
{
$set: {
"orderDocument.customerOrderItems.customerOrderSubItems.$.productId": 10005
}
}
)
This gives the result.

How to update an integer value in Mongodb while preserving type

I want to include some values by a percent.
i.e. give a document with "A": 1700 I want to update it to A: (1700* 1.15)
{$mul: {"A": 1.15}}
but doing so with $mul I get weird results for some values, like 1954.99999998 and it changes the type to a double.
Does a valid syntax exist for an operation like this?
{
$set: {
"A" : {$trunc: ("A" * 1.15)}
}
}
this is not value either
{
$set: {
"A" : NumberInt("A" * 1.15)
}
}
If you take a look into documentation of $mul you will see that this operator can change the element data type and you can't controll it. Unfortunately you can't use any arithmetic operations directly in $set operator. In this case (when you want to apply the additional operations to multiplied value) you need read the element value, apply your custom operations and then save it into DB.

print the length of field (string)

how to print field and length of this field
e.g. I have {name:"aaa"} document is collection "names"
then the expected output is
{name:"aaa", name_legth:3}
Please help.
MongoDB versions <3.2 don't have a text aggregation operator to compute length of a string value stored in a field. If you are using version 3.2 or older, you will need to implement the length computation outside the DB (such as in the controller layer of an MVC architecture).
Version 3.4, though, includes several new and useful aggregation operators including the $strLenCP operator which should serve your purpose. The usage for your case would be as follows:
db.names.aggregate(
[
{
$project: {
"name": 1,
"name_length": { $strLenCP: "$name" }
}
}
]
)
The documentation for the aggregation operator can be found here.

MongoDB findAndModify element in array

I have the data like below:
{
info:{
id:0000,
name:"Iot name",
vendor:"some vendor",
},
location:[
{
lat:0,
lng:0,
status:3,
locID:"uniqueID0"
},{
lat:1,
lng:1,
status:0,
locID:"uniqueID1"
},{
lat:2,
lng:2,
status:1,
locID:"uniqueID2"
}
]}
Need example like findAndModify or something else similar, to find
in the iots collection, location with a unique ID and change his status.
e.g Find in collection iot, element with id=0000 and location with locID="uniqueID1" and set status for that location into 2
Thanks in advance
Apply the $set operator together with the $ positional operator in your update to change set the status field for that location to 2. The $ positional operator will identify the correct element in the array to update without explicitly specifying the position of the element in the array, thus your final update statement should look like:
db.iost.update(
{
"info.id": 0000,
"location.locID": "uniqueID1"
},
{
"$set": {
"location.$.status": 2
}
}
)

How to query nested arrays in mongodb from command line

I have some data structured like this in a mongo collection:
{ "list" : [ { "update_time" : NumberLong(1426690563), "provider" : NumberLong(4) } ] }
What I would like to do is query for all of the entries where the list includes a provider value of 4.
If it helps, all of the list arrays contain only one element.
What I am trying right now is this:
db.collection.find(
{
list: {
provider: 4
}
}
)
This does not work though, and always returns an empty set
Use the dot notation i.e. concatenate the name of the field that contains the array, with a dot (.) and the name of the field in the embedded document and use that as your query:
db.collection.find({"list.provider": 4})
You can also use the $elemMatch operator to specify multiple criteria on an array of embedded documents such that at least one embedded document satisfies all the specified criteria:
db.collection.find({
list: {
$elemMatch: {
provider: 4
}
}
})