Firebase.set() adds extra nodes - javascript

When running the following query using the root directory of my Firebase, extra nodes are added.
Query:
fire.set({
"users":[
{
"0":[
{
"email":"foobar#gmail.com",
"snake":[
{
"highScore":"15"
}
]
}
]
}
]
});
Result
I get the same result when formatting the data in a json file and importing it directly using the Firebase web interface. Did I miss something in the documentation perhaps?

The issue here is that any time you use array syntax, i.e. [ ... ], you're creating an "array" in Firebase, which we do by just creating an object with numeric keys (i.e. 0, 1, 2, ...).
So if you do:
ref.set({ a: 5 });
The resulting object will be:
{ a: 5 }
But if you instead do:
ref.set([{a: 5}, {b: 6}]);
You'll get:
{
'0': { a: 5 },
'1': { b: 6 }
}
So if you just remove the square brackets from the data you're setting, e.g.:
fire.set({
"users": {
"0": {
"email":"foobar#gmail.com",
"snake": {
"highScore":"15"
}
}
}
});
The resulting data in the web interface should match your data exactly.

Related

Trouble using javascript partial.lenses to obtain properties within an array

I'm trying to figure out how to create a lens that'll give me an array of the key values from within an array. Here's a simple example:
const L = require('partial.lenses');
const data = [
{
r: [
{
d: {
one: 1,
two: 2
}
}
]
},
{
r: [
{
d: {
three: 3,
four: 4
}
}
]
}
];
const lens = L.compose (
L.elems,
L.prop ('r'),
L.elems,
L.prop ('d'),
);
const result = L.get (lens, data);
console.log (result);
I want:
[{ one: 1, two: 2 }, { three: 3, four: 4 }]
But get:
{ one: 1, two: 2 }
I'm sure this is trivial, but can't get it quite right. Once my lens correctly selects the array of 'd's I want to use L.modify to get the data with all of the 'd' objects replaced with a string. I think I know how to do once my lens is correct.
Thanks
Use L.collect instead of L.get, L.get returns the first found entity, while L.collect returns all matching entities, similar to [].filter vs [].find.
https://github.com/calmm-js/partial.lenses#l-collect

Get list of values from several paths in json object

I have an object with several nested layers of arrays and subobjects, from which I need to extract the values from some paths. Is there some library or native function which can help me do that? I'm already using Lodash and jQuery, but have a hard time figuring out how to simplify this problem.
Example:
{
a: [
{
b: 0,
c: 1
},
{
b: 1,
c: 2
}
]
}
Now I would like to get a list of all a[0..n].b.
My actual object is much larger and has 3 layers of arrays and a path like syn[0].sem[0].pdtb3_relation[0].sense, so I'd rather not write 3 nested for loops if a library function exists.
You can use forEach() to iterate through array.
var o = {
a: [
{
b: 0,
c: 1
},
{
b: 1,
c: 2
}
]
}
Object.keys(o).forEach(a => o[a].forEach(y => console.log(y.b)));

How to acess a complex JSON [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I am a beginner and, as I began to increase the complexity of JSON, I started to confuse myself by accessing it. How do I access the following JSON? I would like to access the value and keys of the services
{
employers:{
Mike: {
old: 20,
services:{
cut : {
value : 10
}
hair_straightening : {
value: 20
}
}
}
Penny: {
old: 20,
services:{
cut : {
value : 10
}
hair_straightening : {
value: 20
}
}
}
}
}
Everyone has to start somewhere :)
I'm not sure if I completely understand what you're after, but here goes...
First off, it looks like your notation on your object is subtly off when listing your keys. For example, between Mike and Penny you should have a comma separating each of those keys in the larger employers object.
Something like:
employers: {
Mike: {
...
}, //need a comma here
Penny: {
...
}
}
Also, within each of those employers, there should be a comma between the keys for cut and hair_straightening.
services: {
cut: {
value: 10
}, //need a comma here
hair_straightening: {
value: 20
}
}
Now to your actual question...
To get the keys for each of the services, you can use Object.keys(). This function would get you they keys for a given employer. Then you can also grab the values from inside that same function. (Note this is for only one employer; you'd just want to iterate over both and use this same function on each)
function getServices(employer) {
var services = employer.services;
var servicesKeys = Object.keys(services);
var serviceValueMatrix = [];
servicesKeys.forEach(function(service) {
serviceValueMatrix.push([service, employer.services[service].value])
})
return serviceValueMatrix;
}
// assuming you had var yourJSON = { employers: {...} }
// getServices(yourJSON.employers.Mike);
// returns [["cut",10], ["hair_straightening",20]]
Also, given that your JSON object is already in key:value format, you could probably skip the last set of objects in the format of value: 10, value: 20 etc, and instead just make the last tier of your object something like:
services:{
cut: 10,
hair_straightening: 20
}
Then you could just grab services.cut and services.hair_straightening.
Full code below for clarity:
const yourJSON = {
employers: {
Mike: {
old: 20,
services: {
cut: {
value: 10
},
hair_straightening: {
value: 20
}
}
},
Penny: {
old: 20,
services: {
cut: {
value: 10
},
hair_straightening: {
value: 20
}
}
}
}
}
function getServices(employer) {
var services = employer.services;
var servicesKeys = Object.keys(services);
var serviceValueMatrix = [];
servicesKeys.forEach(function(service) {
serviceValueMatrix.push([service, employer.services[service].value])
})
return serviceValueMatrix;
}
console.log(getServices(yourJSON.employers.Mike));
// returns [["cut",10], ["hair_straightening",20]]
your json should look something like this:
{
employers:[
{
name: "Mike",
age: 20,
services: [
{name:"cut",value:10},
{name:"hair_straightening",value:20}
]
},{
name: "Penny",
age: 20,
services: [
{name:"cut",value:10},
{name:"hair_straightening",value:20}
]
}
]
}
You can use Object.keys to get the keys of an object as an array, then you can loop through that nicely.
// in this case json is a variable representing your parsed data
Object.keys(json).map(function(key) {
console.log(json[key])
return json[key].services
})
That would give you an array of services objects.

Proper way in Mongo to update the value of a key without removing old values?

I'm trying to get the following to work but $set's not working. Scratching my head.
What we have in Mongo:
{
_id: "123",
mechanics: {
engine: [
"129hp",
"300hp",
"500hp"
]
}
}
The object that we have in our javascript:
{
mechanics: {
brakes: [
"30cm",
"60cm",
"90cm"
]
}
}
How do you write the update query to make the Mongo doc look like this?
{
_id: "123",
mechanics: {
engine: [
"129hp",
"300hp",
"500hp"
],
brakes: [
"30cm",
"60cm",
"90cm"
]
}
}
Doing $set on mechanics doesn't work because it erases engine and adds in brakes.
What you basically want is "dot notation" which means that your update portion with $set comes out like this:
{ "$set" : { "mechanics.brakes" : [ "30cm", "60cm", "90cm" ] } }
To process an object in JavaScript like you show into this form you would do something like this:
var upd = { "$set": {} };
var obj = {
mechanics: {
brakes: [
"30cm",
"60cm",
"90cm"
]
}
};
Object.keys( obj ).forEach(function(top) {
Object.keys( obj[top] ).forEach(function(inner) {
upd["$set"][ top + "." + inner ] = obj[top][inner]
});
})
Which forms the update statement from the basic obj input and updates the database as you want.

How to Peels off the elements of an array individually in rethinkdb?

I have documents like this:
{
id:1,
"A": [
{
"C": "abc",
"D": [{X:"test"},{X:"test2"}]
},
{
"C": "fg",
"D":["X1"]
}
]
}
How to get all id of document whose tag match A-> D -> X has value "test". I can use concatMap() but when I use it I am not able get "id" field and also cannot use it inside map, is there any similar features like $unwind of Mongodb's aggregation framework?
Similar to :Querying array of nested objects
[Original Question]
{
id:2,
tags[{a:3,b:4},..]
}
Your originial question had this object:
{ id: 2,
tags: [ { a: 3, b: 4 }, ... ] }
You can construct a predicate that finds the relevant documents, and pass it to filter.
r.table(...).filter(r.row('tags')('a').contains(3))('id')
In this case, the ('a') part of the query, when applied to an array, returns an array of the a field of each object in that array, if there is one.
Your edited question has a more complicated object, but the principle is the same:
r.table(...).filter(
r.row('A')('D').concatMap(function(x){return x})('X').contains("test")
)('id')

Categories