Sort array by two fields in different levels - arrays

My input:
[
{
"nfStatusNotificationUri": "http://172.19.0.2:32672/callback/nnrf-nfm/v1/onNFStatusEventPost/4e0becf9-c3ec-4002-a32b-2e35b76469b2",
"subscrCond": {
"serviceName": "namf-evts"
},
"subscriptionId": "36bc52dfdbdd4044b97ef15684706205",
"validityTime": "2022-04-30T16:40:48.274Z",
"reqNotifEvents": [
"NF_DEREGISTERED",
"NF_PROFILE_CHANGED",
"NF_REGISTERED"
]
},
{
"nfStatusNotificationUri": "http://172.19.0.2:32672/callback/nnrf-nfm/v1/onNFStatusEventPost/5319def1-af0b-4b7b-a94e-b787e614c065",
"subscrCond": {
"serviceName": "nbsf-management"
},
"subscriptionId": "e2e904bb52ca4fd6b048841c83a4c38e",
"validityTime": "2022-04-30T16:40:48.26Z",
"reqNotifEvents": [
"NF_DEREGISTERED",
"NF_PROFILE_CHANGED",
"NF_REGISTERED"
]
},
{
"nfStatusNotificationUri": "http://172.19.0.2:32672/callback/nnrf-nfm/v1/onNFStatusEventPost/31dfe10b-4020-47bd-943e-a3e293086b29",
"subscrCond": {
"serviceName": "namf-comm"
},
"subscriptionId": "e508077fab4f4b8d9dd732176a3777b9",
"validityTime": "2022-04-30T16:40:48.273Z",
"reqNotifEvents": [
"NF_DEREGISTERED",
"NF_PROFILE_CHANGED",
"NF_REGISTERED"
]
}
]
I would like to sort it by "subscriptionId" and "serviceName".
I can sort by subscriptionId but I don't know how to specify serviceName to the following expression.
jq -S '.|=sort_by(.subscriptionId)|.[].reqNotifEvents|=sort |del(.[].subscriptionId, .[].validityTime, .[].nfStatusNotificationUri)'

You can parameterize sort_by by a list of keys like so:
sort_by(.subscriptionId, .subscrCond.serviceName)
Online demo

Related

Mongo Query to modify the existing field value with new value + array of objects

I want to update many documents based on the condition in MongoDB.
MODEL is the collection which has the document with below information.
"info": [
{
"field1": "String1",
"field2": "String2"
},
{
"field1": "String1",
"field2": "String_2"
}
],
"var": "x"
I need to update all the "String1" value of field1 with "STRING_NEW". I used the below query to update but not working as expected.
db.model.updateMany(
{ "info.field1": { $exists: true } },
[
{ "$set": {
"info": {
"$map": {
"input": "$info.field1",
"in": {
"$cond": [
{ "$eq": ["$$this.field1", "String1"] },
"STRING_NEW",
$$this.field1
]
}
}
}
} }
]
)
Please have a look and suggest if anything is to be modified in the above query.
Solution 1
With the update with aggregation pipeline, you should iterate the object in info array and update the iterated object by merging the current object with new field1 field via $mergeObjects.
db.model.updateMany({
"info.field1": "String1"
},
[
{
"$set": {
"info": {
"$map": {
"input": "$info",
"in": {
"$cond": [
{
"$eq": [
"$$this.field1",
"String1"
]
},
{
$mergeObjects: [
"$$this",
{
"field1": "STRING_NEW"
}
]
},
"$$this"
]
}
}
}
}
}
])
Demo Solution 1 # Mongo Playground
Solution 2
Can also work with $[<identifier>] positional filtered operator and arrayFilters.
db.model.updateMany({
"info.field1": "String1"
},
{
"$set": {
"info.$[info].field1": "STRING_NEW"
}
},
{
arrayFilters: [
{
"info.field1": "String1"
}
]
})
Demo Solution 2 # Mongo Playground

How to remove arrays inside array if a condition is met

I have an object schema that looks like this:
{
"_id":"ObjectId(""30t00594537da2r7awe083va"")",
"balances":{
"intraday":[
[
1630939075734,
1899.09
],
[
1630939435939,
1899.32
],
[
1632306730756,
0
],
[
1632306759376,
0
],
[
1632272012916,
1372.22
]
]
}
}
I want to remove all arrays within "balances.intraday" array whose the second element is equal to 0.
so my desired array will looks like this:
{
"_id":"ObjectId(""30t00594537da2r7awe083va"")",
"balances":{
"intraday":[
[
1630939075734,
1899.09
],
[
1630939435939,
1899.32
],
[
1632272012916,
1372.22
]
]
}
}
I tried to use the $pull command but it only removes the index and not the whole array.
======================= Edit =======================
Thanks to Tom Slabbaert the solution is as follows :
db._get_collection().update_many(
{},
[
{
"$set": {
"balances.intraday": {
"$filter": {
"input": "$balances.intraday",
"cond": {
"$ne": [
{
"$arrayElemAt": [
"$$this",
1
]
},
0
]
}
}
}
}
}
])
You should use pipelined updates for this, like so:
db.collection.updateMany(
{},
[
{
$set: {
"balances.intraday": {
$filter: {
input: "$balances.intraday",
cond: {
$ne: [
{
$arrayElemAt: [
"$$this",
1
]
},
0
]
}
}
}
}
}
])
Mongo Playground

How to push a new element into existing array or create one if it doesn't exist yet in MongoDb?

I have a script creating a document, updating it and cleaning up.
db.getCollection('things').insert( { _id: 1001,
elemo: { a: "A", b: "B" },
histo: [ ] } } )
db.getCollection('things').update( { _id: 1001 },
[ { $set: {
histo: { $concatArrays: [ "$histo", ["$elemo"] ] } } } ] )
db.getCollection("things").find({ _id: 1001})
db.getCollection('things').remove({ _id: 1001 })
For certain reasons, I'd like to retain the functionality but can't guarantee that the originally empty array actually exists. I need to perform my update in such a way so that an existing array will get an additional element, while a non-existing (yet) one will get created (including said element).
db.getCollection('things').insert( { _id: 1001,
elemo: { a: "A", b: "B" } } )
db.getCollection('things').update( { _id: 1001 },
[ { $set: {
histo: { $concatArrays: [ "$histo", ["$elemo"] ] } } } ] )
db.getCollection("things").find({ _id: 1001})
db.getCollection('things').remove({ _id: 1001 })
The above only creates the field but its value is null, and so additional amendments to it result in null. I'm rather certain that it needs something more around $concatArrays but I can't figure out what. First, I thought I could go $ifnull but it didn't recognize that command (no error, no insertion, no coalescing, nothing).
You can make use of $cond or $ifNull (as you guessed) to check if the key exists or not inside the $concatArrays operator.
Using $cond Method
db.collection.update({
_id: 1001
},
[
{
$set: {
histo: {
"$concatArrays": [
{
"$cond": {
"if": {
"$not": [
"$histo"
]
},
"then": [],
"else": "$histo",
}
},
[
"$elemo"
],
],
}
}
}
])
Mongo Playground Sample Execution
Using $ifNull Method
db.collection.update({
_id: 1001
},
[
{
$set: {
histo: {
"$concatArrays": [
{
"$ifNull": [
"$histo",
[]
],
},
[
"$elemo"
],
],
}
}
}
])
Mongo Playground Sample Execution

Find array in array data in MongoDB

I want find in this document groups:
"document": {
"groups": [
{
"id": "5ccd5f7f34f82b0e3315b2f6"
},
{
"id": "73b43unbfkfmdmddfdf84jjk"
}
]
}
are contains some of my query array groups ID:
[ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ]
A simple find query suffices:
db.collection.find({ 'groups.id' : {$in : [ '5ccd5f7f34f82b0e3315b2f6',
'5cdeded7ace07216f5873b5d',
'5cdee5d114edac2cc00bb333' ] }})

Update array content within another array that don't have key

I have mongoDB content as below:
[
{
"_id":{
"$oid":"57c6699711bd6a0976cabe8a"
},
"ID":"1111",
"FullName":"AAA",
"Category":[
{
"CategoryId":{
"$oid":"57c66ebedcba0f63c1ceea51"
},
"_id":{
"$oid":"57e38a8ad190ea1100649798"
},
"Value":[
{
"Name":""
}
]
},
{
"CategoryId":{
"$oid":"57c3df061eb1e59d3959cc40"
},
"_id":{
"$oid":"57e38a8ad190ea1100649797"
},
"Value":[
[
"111",
"XXXX",
"2005"
],
[
"1212",
"YYYY",
"2000"
],
[
"232323",
"ZZZZZ",
"1999"
]
]
}
]
},
{
"_id":{
"$oid":"57c6699711bd6a0976cabe8a"
},
"ID":"1111",
"FullName":"BBB",
"Category":[
{
"CategoryId":{
"$oid":"57c66ebedcba0f63c1ceea51"
},
"_id":{
"$oid":"57e38a8ad190ea1100649798"
},
"Value":[
{
"Name":""
}
]
},
{
"CategoryId":{
"$oid":"57c3df061eb1e59d3959cc40"
},
"_id":{
"$oid":"57e38a8ad190ea1100649797"
},
"Value":[
[
"4444",
"XXXX",
"2005"
],
[
"7777",
"GGGG",
"2000"
],
[
"8888",
"ZZZZZ",
"1999"
]
]
}
]
}
]
Here I have an array named 'Category' where it contains objects with different category id.
I need to
select a particular category id - '57c3df061eb1e59d3959cc40'
From the above selected Category, we get 'Value' array
From Value array need to find if the second value is equal to 'ZZZZZ' ie. value[1] == 'ZZZZZ'
And now, update the matched value arrays with a new value at the end
Eg:
[
"232323",
"ZZZZZ",
"1999"
]
should be updated to
[
"232323",
"ZZZZZ",
"1999",
"update1"
]
and
[
"8888",
"ZZZZZ",
"1999"
]
should be updated to
[
"8888",
"ZZZZZ",
"1999",
"update1"
]
I have tried as below:
resume.update({
"Category.CategoryId": new ObjectId('57c3df191eb1e59d3959cc43'),
"Category.Value.$.1": 'ZZZZZ'
},
{"$set": {"Category.Value.$.3": "update1"}
}, function(err, resData){
res.send(resData);
});
But, nothing gets updated. Its there any way to get this work. Please help to update the inner array.
Thanks in advance.
Your goal is not possible at the moment since you need to update two positional elements.
There is a JIRA trackable for the sort of behaviour you want here: https://jira.mongodb.org/browse/SERVER-831
It's a problem since you need to match two elements positions:
the Category element with the matched CategoryId
the Value element in the Value array of arrays
If one of these wouldn't be an array it would have been possible.
Anyway, Your update try above was wrong. IF this feature was possible (and it is not!!!) it would have been something like this:
db.resume.update(
{
Category: {
$elemMatch: {
CategoryId: ObjectId('57c3df061eb1e59d3959cc40'),
Value: {
$elemMatch: {
'1': 'ZZZZZ'
}
}
}
}
},
{
$push: {
'Category.$.Value.$': 'update1'
}
}
)
The positional $ operator should be used during the update and not the find like you did, and it will update the first element that matched the query.
Doing the above will return the error:
Too many positional (i.e. '$') elements found in path 'Category.$.Value.$'
Because of the missing feature I explained at the top.
So, currently (version 3.2) you will not be able to do this unless you change your schema.

Resources