Skip to content

Commit e0bb65e

Browse files
committed
Sort keys in updates with multiple
1 parent a0d3d2e commit e0bb65e

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

test/update.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('update: ', function() {
2828
assert.equal(convertUpdate('data', { $set: { field: 'value' } }), 'jsonb_set(data,\'{field}\',\'"value"\')')
2929
})
3030
it('$set multiple', function() {
31-
assert.equal(convertUpdate('data', { $set: { field: 'value', second: 2 } }), 'jsonb_set(jsonb_set(data,\'{second}\',\'2\'::jsonb),\'{field}\',\'"value"\')')
31+
assert.equal(convertUpdate('data', { $set: { field: 'value', second: 2 } }), 'jsonb_set(jsonb_set(data,\'{field}\',\'"value"\'),\'{second}\',\'2\'::jsonb)')
3232
})
3333
it('$set deep', function() {
3434
assert.equal(convertUpdate('data', { $set: { 'a.b': 2 } }), 'jsonb_set(jsonb_set(data,\'{a}\',COALESCE(data->\'a\', \'{}\'::jsonb)),\'{a,b}\',\'2\'::jsonb)')
@@ -47,7 +47,7 @@ describe('update: ', function() {
4747
assert.equal(convertUpdate('data', { $unset: { 'field.inner': 1 } }), 'data #- \'{field,inner}\'')
4848
})
4949
it('$unset multiple', function() {
50-
assert.equal(convertUpdate('data', { $unset: { field: 1, second: 1 } }), 'data #- \'{second}\' #- \'{field}\'')
50+
assert.equal(convertUpdate('data', { $unset: { field: 1, second: 1 } }), 'data #- \'{field}\' #- \'{second}\'')
5151
})
5252

5353
it('$inc', function() {
@@ -87,4 +87,17 @@ describe('update: ', function() {
8787
assert.equal(convertUpdate('data', { $set: { active: true }, $unset: { field: 'value' }, $inc: { purchases: 2 } }), 'jsonb_set(jsonb_set(data,\'{active}\',\'true\'::jsonb) #- \'{field}\',\'{purchases}\',to_jsonb(COALESCE(Cast(data->>\'purchases\' as numeric),0)+2))')
8888
})
8989
})
90+
91+
describe('array by index', function () {
92+
it('$set', function() {
93+
assert.equal(convertUpdate('data', { $set: {
94+
'Items.0': { test: 0 },
95+
'Items.2': { test: 2 },
96+
'Items.1': { test: 1 },
97+
}}),
98+
'jsonb_set(jsonb_set(jsonb_set(jsonb_set(data,\'{Items}\',COALESCE(data->\'Items\', ' +
99+
'\'{}\'::jsonb)),\'{Items,0}\',\'{"test":0}\'::jsonb),\'{Items,1}\',\'{"test":1}\'::jsonb)' +
100+
',\'{Items,2}\',\'{"test":2}\'::jsonb)')
101+
})
102+
})
90103
})

update.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const util = require('./util.js')
22
const convertWhere = require('./index.js')
33

44
function convertOp(input, op, data, fieldName, upsert) {
5-
const pathText = Object.keys(data)[0]
5+
const pathText = util.getPathSortedArray(Object.keys(data))[0]
66
const value = data[pathText]
77
delete data[pathText]
88
if (Object.keys(data).length > 0) {

util.js

+32
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,36 @@ exports.getPostgresTypeName = function(type) {
9292
throw { errmsg: 'argument to $type is not a number or a string', code: 14 }
9393
}
9494
return typeMapping[type] || type
95+
}
96+
97+
function isIntegerStrict(val) {
98+
return val != 'NaN' && parseInt(val).toString() == val
99+
}
100+
101+
exports.getPathSortedArray = function(keys) {
102+
return keys.sort((a, b) => {
103+
if (a == b) {
104+
return 0
105+
}
106+
107+
var aArr = a.split('.')
108+
var bArr = b.split('.')
109+
110+
for (var i = 0; i < aArr.length; i++) {
111+
if (i >= bArr.length) {
112+
return -1
113+
}
114+
115+
if (aArr[i] == bArr[i]) {
116+
continue
117+
}
118+
119+
var aItem = isIntegerStrict(aArr[i]) ? parseInt(aArr[i]) : aArr[i]
120+
var bItem = isIntegerStrict(bArr[i]) ? parseInt(bArr[i]) : bArr[i]
121+
122+
return aItem > bItem ? -1 : 1
123+
}
124+
125+
return 1
126+
})
95127
}

0 commit comments

Comments
 (0)