In Aerospike, how can I add a new key/value pair in nested object stored in bins of type map?
For ex,
I have a bins of type map against which I need to store below key/value pairs.
{
"a" : "apple",
"b" : "ball",
"c" : { "d" : "dog", "e" : "elephant" },
"f" : { "g" : { "h" : "horse" } },
"i" : { "j" : "jackal", "k" : { "l" : "lion", "m" : "monkey" } }
}
Now, I want to update an existing nested object against key "k" to add one more key value pair like below.
"k" : { "l" : "lion", "m" : "monkey", "n" : "nest" }
Final result should be like below.
{
"a" : "apple",
"b" : "ball",
"c" : { "d" : "dog", "e" : "elephant" },
"f" : { "g" : { "h" : "horse" } },
"i" : { "j" : "jackal", "k" : { "l" : "lion", "m" : "monkey", "n" : "nest" } }
}
Any suggestions on how to achieve this?
It's a NodeJS (10.6.0) application & I'm using NodeJS aerospike client (3.6.1) to interact with Aerospike (4.3.0.7).
Updates on nested CDT maps and lists are possible now, using Aerospike server version 4.6 or later and Aerospike Node.js client version 3.12 or later. That update introduced the withContext() function on list and map operations that lets you specify the context in which the list/map operation is to be executed. You can find more information in the documentation for the new CdtContext class.
Here is how you would perform the update given in your example:
const Aerospike = require('aerospike')
const maps = Aerospike.maps
Aerospike.connect().then(async (client) => {
const key = new Aerospike.Key('test', 'test', 'test')
const map = {
"a" : "apple",
"b" : "ball",
"c" : { "d" : "dog", "e" : "elephant" },
"f" : { "g" : { "h" : "horse" } },
"i" : { "j" : "jackal", "k" : { "l" : "lion", "m" : "monkey" } }
}
console.log('BEFORE:', map)
await client.put(key, map)
await client.operate(key, [
maps.put('i', 'n', 'nest')
.withContext((ctx) => ctx.addMapKey('k'))
])
const record = await client.get(key)
console.log('AFTER:', record.bins)
client.close()
}).catch((error) => {
console.error(error)
if (error.client) error.client.close()
})
Here is what you would get, when you run the example:
$ node nested-map-update-example.js
BEFORE: {
a: 'apple',
b: 'ball',
c: { d: 'dog', e: 'elephant' },
f: { g: { h: 'horse' } },
i: { j: 'jackal', k: { l: 'lion', m: 'monkey' } }
}
AFTER: {
a: 'apple',
b: 'ball',
c: { d: 'dog', e: 'elephant' },
f: { g: { h: 'horse' } },
i: { j: 'jackal', k: { l: 'lion', m: 'monkey', n: 'nest' } }
}
You will have to update the full value for the key "i".
Related
I see this error "If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key."
locals {
key_id = {
for x in var.security_rules :
"${x.type}" => x}
}
Is it possible to use ellipsis in a nested for this loop and how can i do it?
The error message means that var.security_rules has multiple items with the same type. For example:
variable "security_rules" {
default = [
{
type = "a"
},
{
type = "b"
},
{
type = "a"
}
]
}
We can see that there are at least 2 items with the same type, which wont be accepted as key in map. What we can do here is to group the items with the same type. This is exactly what ellipsis (...) will accomplish. So:
locals {
key_id = {
for x in var.security_rules : "${x.type}" => x... }
}
The value of key_id in this example will be:
key_id = {
"a" = [
{
"type" = "a"
},
{
"type" = "a"
},
]
"b" = [
{
"type" = "b"
},
]
}
Hi i need merge two object with mergewith in lodash ...
object1 = {
"a": {
"name": "masoud", "age": 3, "user": "masmas"
},
"b" : {
"name": "milad", "age": 13, "user": "milmil"
}
}
object2 = {
"b" : {
"pythonSkill" : 18 , "HTMLSkill" : 15
} ,
"c" : {
"phpSkill" : 15 , "CSSSkill" : 16
},
"a" : {
"javaSkill" : 20 , "reactSkil" : 10
} ,
}
and finally combined object sample :
final = {
"a": {
"name": "masoud", "age": 3, "user": "masmas", "persianLanguage": 20, "englishLanguage": 10
},
"b" : {
"name": "milad", "age": 13, "user": "milmil" , "pythonSkill": 18, "HTMLSkill": 15
}
}
Each object does not have a specific number of internal objects and may be different each time .
one time Object1 have a , b , c , .... , m & other time Object1 have m , n , o , c , ...
Object2 similar object1 ...
Different scenarios
1- if Object1 have "a" and object2 have "a" , finally object must have "a" ..
2- if Object1 have not "a" and object2 have "a" , finally object have not "a" ..
3- if Object1 have "a" and object2 have not "a" , finally object have not "a"
I don't know about using _.mergeWith, this seems to me to be rather difficult but you can use _.mapValues and _.pickBy to achieve the desired result relatively easily
object1 = {
"a": {
"name": "masoud", "age": 3, "user": "masmas"
},
"b" : {
"name": "milad", "age": 13, "user": "milmil"
},
"d" : {
"name": "nassim", "age": 32, "user": "nm1"
}
}
object2 = {
"b" : {
"pythonSkill" : 18 , "HTMLSkill" : 15
} ,
"c" : {
"phpSkill" : 15 , "CSSSkill" : 16
},
"a" : {
"javaSkill" : 20 , "reactSkil" : 10
} ,
}
let final = _.mapValues(_.pickBy(object1, (v,k) => object2[k]), (v, k, o) => {
return { ...v, ...object2[k] }
});
console.log(final)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
I have a Groovy map Map<String, List<String>>. I need to go through each String list, remove those meet a condition (for example length > 3). If all elements removed from the list, remove the key from the map.
For example
{
"1" : ["1", "22,", "333", "4444"],
"2" : ["2", "2222"],
"4" : ["444444"]
}
becomes
{
"1" : ["1", "22,", "333"],
"2" : ["2"],
}
If there's any easy inplace method can do it.
Try this:
m = [
"1" : ["1", "22,", "333", "4444"],
"2" : ["2", "2222"],
"4" : ["444444"]
]
m.each {String k, List v ->
v.removeAll { it.length() > 3}
if (m[k].isEmpty()) {
m.remove(k)
}
}
m.each { k, v -> println "${k} : ${v}"}
An alternative to #ou_ryperd's answer that doesn't mutate the original map is:
def m = [
"1" : ["1", "22", "333", "4444"],
"2" : ["2", "2222"],
"4" : ["444444"]
]
def newMap = m.collectEntries { k, v -> [k, v.findAll { it.length() < 4 }] }
.findAll { k, v -> v.size() > 0 }
I'm having some trouble with my JsonBuilder. I'd like the output to look like the following:
{
"appointmentCheckResult": [
{
"itexxmCode": "98765432",
" needAppointmentCheckFlag ": "Y"
},
{
"itemCode": "98765433",
"needAppointmentCheckFlag": "N"
}
]
}
what I get is :
{
"appointmentCheckResult": {
"xxx": [
{
"itemCode": "12345",
"needAppointmentCheckFlag": "Y"
},
{
"itemCode": "5678902",
"needAppointmentCheckFlag": "Y"
}
]
}
}
The code is shown below:
import groovy.json.*
def json = new JsonBuilder()
def itemCode = ['12345', '5678902']
def needFlag = 'Y'
json.appointmentCheckResult{xxx([itemCode].transpose().collect {[itemCode:it[0], needAppointmentCheckFlag:needFlag]})}
println JsonOutput.prettyPrint(json.toString())
How can I get rid of the XXX and the "{" which in front of XXX?
No idea how you're expecting to get the Y and N in the output, or itexxmCode as a key... But assuming they're typos in the expected output, you need something like:
json {
appointmentCheckResult(
[itemCode].transpose().collect {
[itemCode: it[0], needAppointmentCheckFlag: needFlag]
}
)
}
Can I return something like:
{
"c/12313" = 1,
"c/24223" = 2,
"c/43423" = 3,
...
}
from an AQL query? The idea is something like (this non-working code):
for c in my_collection
return { c._id : c.sortOrder }
where sortOrder is some property on my documents.
Yes, it is possible to have dynamic attribute names:
LET key = "foo"
LET value = "bar"
RETURN { [ key ]: value } // { "foo": "bar" }
An expression to compute the attribute key has to be wrapped in [ square brackets ], like in JavaScript.
This doesn't return quite the desired result however:
FOR c IN my_collection
RETURN { [ c._id ]: c.sortOrder }
[
{ "c/12313": 1 },
{ "c/24223": 2 },
{ "c/43423": 3 },
...
]
To not return separate objects for every key, MERGE() and a subquery are required:
RETURN MERGE(
FOR c IN my_collection
RETURN { [ c._id ]: c.sortOrder }
)
[
{
"c/12313": 1,
"c/24223": 2,
"c/43423": 3,
...
}
]