Add array at specific index/position in jsonb Postgresql field - arrays

I'm wondering if there's a way to append array to a specific index/position in an jsonb array in Postgresql 9.6?
Let's imagine that my code below is my json:
{
"date": "2018-02-12",
"author": "devoplex",
"block": [
{ "color": "#C70039", "title": "Fruit" },
{ "color": "#DAF7A6", "title": "Vegetable" },
{ "color": "#DAF7A6", "title": "Meat" }
]
}
I want to append this object in my "block" array:
{ "color": "#581845", "title": "Candy" }
But I want this object to become the third index/position without replacing anything. So finally I can have this result:
{
"date": "2018-02-12",
"author": "devoplex",
"block": [
{ "color": "#C70039", "title": "Fruit" }, <---- Initial line
{ "color": "#DAF7A6", "title": "Vegetable" }, <---- Initial line
{ "color": "#581845", "title": "Candy" }, <---- New line
{ "color": "#DAF7A6", "title": "Meat" } <---- Initial line
]
}
This example in not my actual code but it's the same issue. This is for the construction of a form, so it need to be in a specific order or else it won't make any sense. Thanks you.

an ugly wheel, but nothing smarter comes fast:
with c(jb) as (values('{
"date": "2018-02-12",
"author": "devoplex",
"block": [
{ "color": "#C70039", "title": "Fruit" },
{ "color": "#DAF7A6", "title": "Vegetable" },
{ "color": "#DAF7A6", "title": "Meat" }
]
}'::jsonb))
, m as (select jb,e,case when o <3 then o else o+1 end o from c, jsonb_array_elements(jb->'block') with ordinality t(e,o) union all select jb, '{ "color": "#581845", "title": "Candy" }',3 from c)
, n as (select distinct jb,jsonb_agg(e) over (order by o) a from m)
select jsonb_pretty(jsonb_set(jb,'{block}',a)) from n order by length(a::text) desc limit 1;
jsonb_pretty
----------------------------------
{ +
"date": "2018-02-12", +
"block": [ +
{ +
"color": "#C70039", +
"title": "Fruit" +
}, +
{ +
"color": "#DAF7A6", +
"title": "Vegetable"+
}, +
{ +
"color": "#581845", +
"title": "Candy" +
}, +
{ +
"color": "#DAF7A6", +
"title": "Meat" +
} +
], +
"author": "devoplex" +
}
of course you should replace 3 with other digit if you want it in other index... http://dbfiddle.uk/?rdbms=postgres_10&fiddle=ccef24ef615b30eec07be9d1be5a1f8d here's example with index taken out of main query to ind CTE

Related

Azure Data Factory - How to transform object with dynamic keys to array in a data flow?

After spending many hours of reading the documentation, following some tutorials and trial & error, i just can't figure it out; how can I transform the following complex object with key objects to an array using a data flow in Azure Data Factory?
Input
{
"headers": {
"Content-Length": 1234
},
"body": {
"00b50a39-8591-3db3-88f7-635e2ec5c65a": {
"id": "00b50a39-8591-3db3-88f7-635e2ec5c65a",
"name": "Example 1",
"date": "2023-02-09"
},
"0c206312-2348-391b-99f0-261323a94d95": {
"id": "0c206312-2348-391b-99f0-261323a94d95",
"name": "Example 2",
"date": "2023-02-09"
},
"0c82d1e4-a897-32f2-88db-6830a21b0a43": {
"id": "00b50a39-8591-3db3-88f7-635e2ec5c65a",
"name": "Example 3",
"date": "2023-02-09"
},
}
}
Expected output
[
{
"id": "00b50a39-8591-3db3-88f7-635e2ec5c65a",
"name": "Example 1",
"date": "2023-02-09"
},
{
"id": "0c206312-2348-391b-99f0-261323a94d95",
"name": "Example 2",
"date": "2023-02-09"
},
{
"id": "00b50a39-8591-3db3-88f7-635e2ec5c65a",
"name": "Example 3",
"date": "2023-02-09"
}
]
AFAIK, Your JSON keys are dynamic. So, getting the desired result using dataflow might not be possible.
In this case, you can try the below approach as a workaround. This will work only if all of your key's length is same.
This is my Pipeline:
First I have used a lookup activity to get the JSON file and converted the lookup output to a string and stored in a variable using below expression.
#substring(string(activity('Lookup1').output.value[0].body),2,sub(length(string(activity('Lookup1').output.value[0].body)),4)).
Then I have used split on that String variable with '},"' and stored in an array variable using below expression.
#split(variables('res_str'),'},"')
It will give the array like below.
Give that array to a ForEach and inside ForEach use an append variable activity to store the keys into an array with below expression.
#take(item(), 36)
Now, I got the list of keys in an array, after the above ForEach use another ForEach activity to get the desired array of objects. Use append variable actvity inside ForEach and give the below expression for it.
#activity('Lookup1').output.value[0].body[item()]
Result array after ForEach will be:
If you want to store the above JSON into a file, you need to use OPENJSON from SQL. This is because copy activity additonal column only supports string type not an array type.
Use a SQL dataset on copy activity source and give the below SQL script in the query.
DECLARE #json NVARCHAR(MAX)
SET #json =
N'#{variables('json_arr')}'
SELECT * FROM
OPENJSON ( #json )
WITH (
id varchar(200) '$.id' ,
name varchar(32) '$.name',
date varchar(32) '$.date'
)
In Sink, give a JSON dataset and select Array of Objects as File pattern.
Execute the pipeline and you will get the above array inside a file.
This is my Pipeline JSON:
{
"name": "pipeline1",
"properties": {
"activities": [
{
"name": "Lookup1",
"type": "Lookup",
"dependsOn": [],
"policy": {
"timeout": "0.12:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"source": {
"type": "JsonSource",
"storeSettings": {
"type": "AzureBlobFSReadSettings",
"recursive": true,
"enablePartitionDiscovery": false
},
"formatSettings": {
"type": "JsonReadSettings"
}
},
"dataset": {
"referenceName": "Json1",
"type": "DatasetReference"
},
"firstRowOnly": false
}
},
{
"name": "Lookup output to Str",
"description": "",
"type": "SetVariable",
"dependsOn": [
{
"activity": "Lookup1",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"variableName": "res_str",
"value": {
"value": "#substring(string(activity('Lookup1').output.value[0].body),2,sub(length(string(activity('Lookup1').output.value[0].body)),4))",
"type": "Expression"
}
}
},
{
"name": "Split Str to array",
"type": "SetVariable",
"dependsOn": [
{
"activity": "Lookup output to Str",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"variableName": "split_arr",
"value": {
"value": "#split(variables('res_str'),'},\"')",
"type": "Expression"
}
}
},
{
"name": "build keys array using split array",
"type": "ForEach",
"dependsOn": [
{
"activity": "Split Str to array",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"items": {
"value": "#variables('split_arr')",
"type": "Expression"
},
"isSequential": true,
"activities": [
{
"name": "take first 36 chars of every item",
"type": "AppendVariable",
"dependsOn": [],
"userProperties": [],
"typeProperties": {
"variableName": "keys_array",
"value": {
"value": "#take(item(), 36)",
"type": "Expression"
}
}
}
]
}
},
{
"name": "build final array using keys array",
"type": "ForEach",
"dependsOn": [
{
"activity": "build keys array using split array",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"items": {
"value": "#variables('keys_array')",
"type": "Expression"
},
"isSequential": true,
"activities": [
{
"name": "Append variable1",
"description": "append every object to array",
"type": "AppendVariable",
"dependsOn": [],
"userProperties": [],
"typeProperties": {
"variableName": "json_arr",
"value": {
"value": "#activity('Lookup1').output.value[0].body[item()]",
"type": "Expression"
}
}
}
]
}
},
{
"name": "Just for Res show",
"type": "SetVariable",
"dependsOn": [
{
"activity": "build final array using keys array",
"dependencyConditions": [
"Succeeded"
]
}
],
"userProperties": [],
"typeProperties": {
"variableName": "final_res_show",
"value": {
"value": "#variables('json_arr')",
"type": "Expression"
}
}
},
{
"name": "Copy data1",
"type": "Copy",
"dependsOn": [
{
"activity": "Just for Res show",
"dependencyConditions": [
"Succeeded"
]
}
],
"policy": {
"timeout": "0.12:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"source": {
"type": "AzureSqlSource",
"sqlReaderQuery": "DECLARE #json NVARCHAR(MAX)\nSET #json = \n N'#{variables('json_arr')}' \n \nSELECT * FROM \n OPENJSON ( #json ) \nWITH ( \n id varchar(200) '$.id' , \n name varchar(32) '$.name', \n date varchar(32) '$.date'\n )",
"queryTimeout": "02:00:00",
"partitionOption": "None"
},
"sink": {
"type": "JsonSink",
"storeSettings": {
"type": "AzureBlobFSWriteSettings"
},
"formatSettings": {
"type": "JsonWriteSettings",
"filePattern": "arrayOfObjects"
}
},
"enableStaging": false
},
"inputs": [
{
"referenceName": "AzureSqlTable1",
"type": "DatasetReference"
}
],
"outputs": [
{
"referenceName": "Target_JSON",
"type": "DatasetReference"
}
]
}
],
"variables": {
"res_str": {
"type": "String"
},
"split_arr": {
"type": "Array"
},
"keys_array": {
"type": "Array"
},
"final_res_show": {
"type": "Array"
},
"json_arr": {
"type": "Array"
}
},
"annotations": []
}
}
Result file:

Select random id from list in jq and update value

I have some sample payload that I am going to be receiving, it looks like this:
[
{
"Id": "9",
"Line": [
{
"Amount": 100,
"Description": "Weekly Gardening Service",
"DetailType": "SalesItemLineDetail",
"Id": "1",
"LineNum": 1,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Landscaping Services",
"value": "45"
},
"ItemRef": {
"name": "Gardening",
"value": "6"
},
"Qty": 4,
"TaxCodeRef": {
"value": "TAX"
},
"UnitPrice": 25
}
},
{
"Amount": 100,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}
]
},
{
"Id": "10",
"Line": [
{
"Amount": 140,
"Description": "Weekly Gardening Service",
"DetailType": "SalesItemLineDetail",
"Id": "1",
"LineNum": 1,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Landscaping Services",
"value": "45"
},
"ItemRef": {
"name": "Gardening",
"value": "6"
},
"Qty": 4,
"TaxCodeRef": {
"value": "NON"
},
"UnitPrice": 35
}
},
{
"Amount": 35,
"Description": "Pest Control Services",
"DetailType": "SalesItemLineDetail",
"Id": "2",
"LineNum": 2,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Pest Control Services",
"value": "54"
},
"ItemRef": {
"name": "Pest Control",
"value": "10"
},
"Qty": 1,
"TaxCodeRef": {
"value": "NON"
},
"UnitPrice": 35
}
},
{
"Amount": 175,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}
]
}
]
These I know are valid and I need to cross reference them, by id, in another payload I am receiving. But, the data I am receiving I can't assume to have valid ID's.
So, I want to take all the valid Ids from above, and shove them, randomly, into the sample data I have, that looks like this ($.invoices[].qbId):
[
{
"id": "fb2430c5-5970-46b0-9947-aaa0b9f177bb",
"invoices": [
{
"description": "2022-02-03 - 179",
"dueDate": "2022-02-03T22:51:10.206Z",
"id": "6f904b18-71c6-4fec-a016-7452f6a6b1dc",
"invoiceDate": "2022-02-03T22:51:10.347Z",
"openBalance": 200,
"paidAmount": 200,
"qbId": "1",
"totalAmount": 212
}
]
},
{
"id": "fa5b77b5-bfd4-4178-ac31-386ec83f530c",
"invoices": [
{
"description": "2022-01-12 - 95",
"dueDate": "2022-01-12T14:08:26.219Z",
"id": "05a58be3-4396-4c15-b9c2-ece68cb2b3fb",
"invoiceDate": "2022-01-12T14:08:26.399Z",
"openBalance": 7.33,
"paidAmount": 7.33,
"qbId": "",
"totalAmount": 7.33
},
{
"description": "2022-01-12 - 95",
"dueDate": "2022-01-12T14:08:26.219Z",
"id": "91f5ecd0-e18d-4029-8745-143323e02007",
"invoiceDate": "2022-01-12T14:08:26.580Z",
"openBalance": 53.13,
"paidAmount": 53.13,
"qbId": "",
"totalAmount": 53.13
}
]
}
]
this jq will get me my ids jq '.QueryResponse.Invoice | map(.Id)' which can be readily consumed by jq. The question now is (and this is what I don't know) how to randomly choose from this array and update the sample payload:
jq 'map(. + {
invoices : .invoices | map(. + {qbId: ??random here })
})
'
If I understood correctly, you want to replace each id field (spelling may differ, sometimes it's Id) with a randomly generated id string.
This solution first extracts the paths of all such id fields (in various spellings) using jq, then iterates over the result in the shell, using uuidgen to generate an id for each, which is fed into another jq call which uses setpath to change the value at the paths saved to the ids generated:
file="input.json"
jq -c '
paths(.. | scalars) | select(.[-1] == ("id", "Id", "ID")) | tojson
' "$file" |
while read -r json; do printf '["%s",%s]\n' "$(uuidgen)" "$json"; done |
jq -n --argfile file "$file" '
reduce inputs as [$id,$json] ($file; setpath($json | fromjson; $id))
'
[
{
"Id": "10162eb7-29ba-4b60-ad20-e5b1133eca63",
"Line": [
{
"Amount": 100,
"Description": "Weekly Gardening Service",
"DetailType": "SalesItemLineDetail",
"Id": "272832df-a8f5-4877-92de-1545150afc33",
"LineNum": 1,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Landscaping Services",
"value": "45"
},
"ItemRef": {
"name": "Gardening",
"value": "6"
},
"Qty": 4,
"TaxCodeRef": {
"value": "TAX"
},
"UnitPrice": 25
}
},
{
"Amount": 100,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}
]
},
{
"Id": "190b0e50-e007-46a4-b1ca-c3efb762629c",
"Line": [
{
"Amount": 140,
"Description": "Weekly Gardening Service",
"DetailType": "SalesItemLineDetail",
"Id": "f7067227-56d4-4849-873a-3ee5c336999e",
"LineNum": 1,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Landscaping Services",
"value": "45"
},
"ItemRef": {
"name": "Gardening",
"value": "6"
},
"Qty": 4,
"TaxCodeRef": {
"value": "NON"
},
"UnitPrice": 35
}
},
{
"Amount": 35,
"Description": "Pest Control Services",
"DetailType": "SalesItemLineDetail",
"Id": "181d7c6b-0afa-4f44-a568-2c482fc5c285",
"LineNum": 2,
"SalesItemLineDetail": {
"ItemAccountRef": {
"name": "Pest Control Services",
"value": "54"
},
"ItemRef": {
"name": "Pest Control",
"value": "10"
},
"Qty": 1,
"TaxCodeRef": {
"value": "NON"
},
"UnitPrice": 35
}
},
{
"Amount": 175,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}
]
}
]
This shows how to select elements at random from an array, assuming a bash or sufficiently bash-like environment:
#!/bin/bash
< /dev/urandom tr -cd '0-9' | fold -w 1 | jq -MRnc '
# Output: a prn in range(0;$n) where $n is `.`
def prn:
if . == 1 then 0
else . as $n
| ([1, (($n-1)|tostring|length)]|max) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;
# Input: an array
# Output: an array, being a selection of $k elements from . chosen at random without replacement
def prns($k):
if $k <= 0 then []
else . as $in
| length as $n
| if $k > $n then "no can do" | error
else ($n|prn) as $ix
| [$in[$ix]] + (($in[0:$ix] + $in[$ix+1:])|prns($k-1))
end
end;
# Two illustrations
# Three from range(0,10) (with replacement):
[range(0;10) | ( ["a", "b", "c"] | .[length|prn]) ],
# Three from an array, without replacement:
([range(0;10)] | prns(3))
'

remove too close time elements from a json array

I am having an array of json object which contain timing and data.
Basically, each element, contain timing, id and user as below
[
{
"id": "abc",
"ts": "2017-08-17T20:42:12.557229",
"userid": "seb"
},
{
"id": "def",
"ts": "2017-08-17T20:42:52.724773",
"userid": "seb"
},
{
"id": "ghi",
"ts": "2017-08-17T20:42:53.724773",
"userid": "matt"
},
{
"id": "jkl",
"ts": "2017-08-17T20:44:50.557229",
"userid": "seb"
},
{
"id": "mno",
"ts": "2017-08-17T20:44:51.724773",
"userid": "seb"
},
{
"id": "pqr",
"ts": "2017-08-17T20:50:52.724773",
"userid": "seb"
}
]
My goal is to remove object too close to each other if the userid is the same. if the time difference is below 2 sec, we remove the element.
From the list, I should get the list
[
{
"id": "abc",
"ts": "2017-08-17T20:42:12.557229",
"userid": "seb"
},
{
"id": "def",
"ts": "2017-08-17T20:42:52.724773",
"userid": "seb"
},
{
"id": "ghi",
"ts": "2017-08-17T20:42:53.724773",
"userid": "matt"
},
{
"id": "pqr",
"ts": "2017-08-17T20:50:52.724773",
"userid": "seb"
}
]
even if the 2 objects for user matt and seb are too close to each other below 2seconds, we have to keep the element as it's not the same user
"ts": "2017-08-17T20:42:52.724773" for seb
and
"ts": "2017-08-17T20:42:53.724773" for matt
Any idea how to code it in Ruby ? I always compared the element n to the n-1 and delete the n-1 if needed
require 'time'
result = []
timestamps = {}
data.each do |item|
ts = timestamps[item['userid']]
if ts.nil? or Time.parse(item['ts']) - Time.parse(ts) > 2
result.push(item)
timestamps[item['userid']] = item['ts']
end
end
puts result
What about the code below?
It changes the order of the records, but you could re-sort them if needed.
require 'date'
def time_elapsed_in_seconds(start_time, end_time)
((end_time - start_time) * 24 * 60 * 60).to_i
end
def too_close?(first_time, second_time, threshold = 2)
time_elapsed_in_seconds(first_time, second_time) < threshold
end
def datetimes(a, b)
return [DateTime.parse(a), DateTime.parse(b)]
end
def should_reject_record?(record, next_record)
datetimes = datetimes(record[:ts], next_record[:ts])
record[:userid] == next_record[:userid] && too_close?(*datetimes)
end
def filter_records(records)
sorted = records.sort_by{|record| [record[:userid], record[:ts]] }
sorted.select.with_index do |record, index|
previous_record = sorted[index-1]
record == sorted.first || !should_reject_record?(previous_record, record)
end
end
records = [
{
"id": "abc",
"ts": "2017-08-17T20:42:12.557229",
"userid": "seb"
},
{
"id": "def",
"ts": "2017-08-17T20:42:52.724773",
"userid": "seb"
},
{
"id": "ghi",
"ts": "2017-08-17T20:42:53.724773",
"userid": "matt"
},
{
"id": "jkl",
"ts": "2017-08-17T20:44:50.557229",
"userid": "seb"
},
{
"id": "mno",
"ts": "2017-08-17T20:44:51.724773",
"userid": "seb"
},
{
"id": "pqr",
"ts": "2017-08-17T20:50:52.724773",
"userid": "seb"
}
]
puts filter_records(records)

Aggregating array of values in elasticsearch

I need to aggregate an array as follows
Two document examples:
{
"_index": "log",
"_type": "travels",
"_id": "tnQsGy4lS0K6uT3Hwzzo-g",
"_score": 1,
"_source": {
"state": "saopaulo",
"date": "2014-10-30T17",
"traveler": "patrick",
"registry": "123123",
"cities": {
"saopaulo": 1,
"riodejaneiro": 2,
"total": 2
},
"reasons": [
"Entrega de encomenda"
],
"from": [
"CompraRapida"
]
}
},
{
"_index": "log",
"_type": "travels",
"_id": "tnQsGy4lS0K6uT3Hwzzo-g",
"_score": 1,
"_source": {
"state": "saopaulo",
"date": "2014-10-31T17",
"traveler": "patrick",
"registry": "123123",
"cities": {
"saopaulo": 1,
"curitiba": 1,
"total": 2
},
"reasons": [
"Entrega de encomenda"
],
"from": [
"CompraRapida"
]
}
},
I want to aggregate the cities array, to find out all the cities the traveler has gone to. I want something like this:
{
"traveler":{
"name":"patrick"
},
"cities":{
"saopaulo":2,
"riodejaneiro":2,
"curitiba":1,
"total":3
}
}
Where the total is the length of the cities array minus 1. I tried the terms aggregation and the sum, but couldn't output the desired output.
Changes in the document structure can be made, so if anything like that would help me, I'd be pleased to know.
in the document posted above "cities" is not a json array , it is a json object.
If changing the document structure is a possibility I would change cities in the document to be an array of object
example document:
cities : [
{
"name" :"saopaulo"
"visit_count" :"2",
},
{
"name" :"riodejaneiro"
"visit_count" :"1",
}
]
You would then need to set cities to be of type nested in the index mapping
"mappings": {
"<type_name>": {
"properties": {
"cities": {
"type": "nested",
"properties": {
"city": {
"type": "string"
},
"count": {
"type": "integer"
},
"value": {
"type": "long"
}
}
},
"date": {
"type": "date",
"format": "dateOptionalTime"
},
"registry": {
"type": "string"
},
"state": {
"type": "string"
},
"traveler": {
"type": "string"
}
}
}
}
After which you could use nested aggregation to get the city count per user.
The query would look something on these lines :
{
"query": {
"match": {
"traveler": "patrick"
}
},
"aggregations": {
"city_travelled": {
"nested": {
"path": "cities"
},
"aggs": {
"citycount": {
"cardinality": {
"field": "cities.city"
}
}
}
}
}
}

Sorting arrays in Mongo

H have json document with array. As I can't add to beginning of array with push or addtoset I need to sort array. Example
{
"Component": [
{
"Id": "PDP-1",
"Links": {"Link": [
{
"Text": "Western Division",
"Url": "/1x7-en70ai/last-minute-holidays-western-division",
"Title": "Last minute holidays Western Division"
},
{
"Text": "Browse Regions ",
"Url": "/1x7-en6uly-10ts/last-minute-holidays-gambia/regions",
"Title": "Last minute holidays Gambia",
"Style": "BrowseForMore"
},
{
"Text": "City of Banjul",
"Url": "/1x6-en6vq7/holidays-city-of-banjul",
"Title": "City of Banjul Holidays"
},
{
"Text": "Western Division",
"Url": "/1x6-en70ai/holidays-western-division",
"Title": "Western Division Holidays"
}
]},
"Title": "Regions",
"Type": "PDP"
},
{
"Id": "PDP-2",
"Links": {"Link": [
{
"Text": "Bijilo",
"Url": "/1x7-enbmy6/last-minute-holidays-bijilo",
"Title": "Last minute holidays Bijilo"
},
{
"Text": "Browse Cities ",
"Url": "/1x7-en6uly-10tt/last-minute-holidays-gambia/cities",
"Title": "Last minute holidays Gambia",
"Style": "BrowseForMore"
},
{
"Text": "Banjul Beach",
"Url": "/1x6-enakgm/holidays-banjul-beach",
"Title": "Banjul Beach Holidays"
},
{
"Text": "Bijilo",
"Url": "/1x6-enbmy6/holidays-bijilo",
"Title": "Bijilo Holidays"
},
{
"Text": "Brufut Heights",
"Url": "/1x6-encok8/holidays-brufut-heights",
"Title": "Brufut Heights Holidays"
},
{
"Text": "Kololi",
"Url": "/1x6-enpnle/holidays-kololi",
"Title": "Kololi Holidays"
},
{
"Text": "Kotu",
"Url": "/1x6-enq067/holidays-kotu",
"Title": "Kotu Holidays"
}
]},
"Title": "Cities",
"Type": "PDP"
}
],
"Id": "118431",
"Template": {
"PageTemplate": {
"Code": "2B2",
"text": "041 - TEMP2 - COP_CONCOU_{LAST MINUTE}"
},
"Category": {
"Code": "1X7",
"Type": "Product",
"text": "Last minute holidays"
},
"GeoObject": {
"Code": "EN6ULY",
"text": "Gambia, The"
},
"GeoObjectType": {
"Code": "1A",
"text": "Political"
},
"GeoObjectSubType": {
"Code": "10TR",
"text": "Country"
}
},
"Type": "Content",
"Url": "/1x7-en6uly/last-minute-holidays-gambia",
"_id": {"$oid": "528492d4c90fa9fcd0436929"}
}
I want to sort this by Style in Links.Link 'BrowseForMore'. Any idea how to do it? I thought I could add dummy array with push which could then sort it the way I want. Any help appreciated
You appear to want to update the array and keep the sort order with your Links.Link.Style value at the front of the list. In which case use the $sort modifier with update.
db.collection.update(
{ _id: id },
{ $push: { "Links.Link: {$each: [doc], $sort { Style: -1 }}} }
)
The $each operator is required even if there is only one document, but can take many.
if you are trying to use $addToSet to maintain unique documents the official MongoDB line is that sets are considered to be unordered and hence the modifiers are not available here.

Resources