node.js: iterate through nested firebase JSON tree - javascript

I am trying to access a nested firebase tree from node.js as follows.
ref.forEach( function(snapshot0) {
snapshot0.child("Meals").forEach( function(snapshot1) {
console.log(snapshot1.val);
});
});
And it will just always tell me that ref.forEach is not a function.
TypeError: refPrices.forEach is not a function
I have defined these as follows.
var db = admin.database();
var ref = db.ref("users");
I have checked these answers
How do I iterate through a large dataset with Firebase / Node.js?
Iterating through nested firebase objects - Javascript
Iterate through nested JSON tree and change values
But I believe according to those my above code should be working, so I am really confused. Also, I have tried to replace forEach by a loop, but I get
TypeError: ref.length is not a function
so I cannot calculate the maximum value of the loop. I have also tried
ref.once("value", function(snapshot0) {
snapshot0.child("Meals").forEach( function(snapshot1) {
console.log(snapshot1.val);
});
});
but in that case it throws the error
TypeError: snapshot0.forEach is not a function
so I pretty much still have the same problem. I cannot work out where my example is different from the links to the solutions above?
Edit: here is what my JSON tree looks like (as per Frank's request). I have only shortened the userID's a little bit.
"users" : {
"ugkvjTuXW2" : {
"Meals" : {
"Meal_2" : {
"priceHist" : [ null, 1, 1, 1, 1, 1, 1 ]
},
"Meal_3" : {
"priceHist" : [ null, 1, 1, 1, 1, 10, 1 ]
},
"Meal_4" : {
"priceHist" : [ null, 1, 1, 1, 1, 1, 1 ]
},
"Meal_5" : {
"priceHist" : [ null, 1, 1, 1, 1, 1, 1 ]
}
}
},
"oJJ1Cojia2" : {
"Meals" : {
"Meal_2" : {
"priceHist" : [ null, 1, 4, 4, 1, 1, 1 ]
},
"Meal_3" : {
"priceHist" : [ null, 1, 1, 1, 1, 10, 1 ]
},
"Meal_4" : {
"priceHist" : [ null, 1, 5, 1, 1, 7, 1 ]
},
"Meal_5" : {
"priceHist" : [ null, 3, 1, 1, 1, 12, 1 ]
}
}
}
}

On your first snippet: a DatabaseReference is nothing more than the path of some data in your Firebase Database. The data itself is not in the ref, so you can't loop over the data.
It's hard to say what's going wrong in your second snippet, because we have no idea what the data under /users looks like. Please edit your question to include a minimal snippet of the JSON (as text, no screenshots please) that is necessary to reproduce the problem. You can get this by clicking the "Export JSON" link in your Firebase Database console.
Update
If you retrieve the value of /users, you get a snapshot with all users. So the first level of children are a node for each user. Then under there you have the meals for each user. Your code is missing a loop for the first level, so:
var ref = admin.database().ref("users");
ref.once("value", function(userSnapshot) {
userSnapshot.forEach(function(userSnapshot) {
userSnapshot.child("Meals").forEach(function(mealSnapshot) {
console.log(mealSnapshot.val());
});
});
});
Also note that you're using numeric indexes, which Firebase recommends against. See this blog post on arrays and the Firebase documentation on handling collections.

Related

How to update nested array inside an Object in MongoDB

I want to update progress of the particular course by finding userId and coursename. I have seen all the MongoDB queries for that but still not getting the desired output. Sometimes got an empty array while data exist in DB. I am not getting if I have to add value inside the progress array then how I will apply the MongoDB query on that:
{
userId: "218u092ue029ie",
ABC:{
"courseName": "course1",
"progress": [
1,2,3
]
},
XYZ:{
"courseName": "course2",
"progress": [
1,2
]
},
pqr:{
"courseName": "course3",
"progress": [
1,2,3,4,5
]
}
}
Try like this:
db.yourCollection.updateOne(
{ userId: "218u092ue029ie", "ABC.courseName": "course1" },
{ $set: { "ABC.progress.$": [1, 2, 3, 4] } }
);

Using [Sequelize.Op.in] for json object arrays

I have a meta tag table which contains a tagId and a value.
I have an array of tagId,value objects
Eg : [{'tagId':2, 'value':33}, {'tagId':2, 'value':34}, {'tagId':1,
'value':34}, etc.. ]
My metaTag table consists of a virtual column which will return the {tagId,value} object for each entry in table. My question is how can I select rows with each {tagId, value} pair in the array.
In other words, I want to be able to do something like
[Sequelize.Op.in]:[{'tagId':2, 'value':33}, {'tagId':2, 'value':34}]
This doesn't work, however.
I might not have explained this well, English isn't my first language. Please ask if you need any clarification on the issue.
You can attain this by using Op.or. If I am not wrong you are trying
('tagId' = 2 and 'value' = 33) or ('tagId' = 2, 'value' = 34):
where: { [Sequelize.Op.or]: [{'tagId':2, 'value':33}, {'tagId':2, 'value':34}] }
You can add n number of values to the or array. As per your requirement.
if you want to do a in like this:
tagId in(2, 2) and value in (33, 34) then:
where: {'tagId':[2], 'value':[33, 34]}
You don't need the explicit Op.in for the array.
You can use there:
const myDeviceIds = [1, 2, 3, 4, 7, 9, 29];
const macroDevices = await MacroDevice.findAll({
where: {
deviceId: {
[Op.in]: myDeviceIds,
},
life: {
[Op.not]: null,
},
status: {
[Op.is]: null,
}
},
order: [
['id', 'DESC']
],
limit,
offset,
include: [
Macro,
Targets,
]
});

Grouping an object with two attributes for table

i have an api in rest that return the following object :
The object
[
{
"attributes": {
"CodAP" : 1,
"Period": 1991,
"People": 6000,
"Child" : 3000
}
},
{
"attributes": {
"CodAP" : 1,
"Period": 2000,
"People": 5000,
"Child" : 1000
}
}
]
Explanation
I need to add these values in the following sequence in the table:
Versions
I am using the version of lodash : 4.17.4
Also am using vue.js at the version: 2.3.3
Note: I even asked this question but could not express myself in the best way. Now I think it's clearer what I need. follows my previous post: Grouping an object with two attributes
Maybe you mean this?
_.groupBy(obj, (v) => v.attributes.CodAP)
https://jsfiddle.net/wk7zL0gr/

Accessing specific values in JSON object

I can't figure out what I'm doing wrong when accessing this JSON object:
{ Items:
[ { mId: 'who' },
{ mId: 'am' },
{ mId: 'I' } ],
Count: 3,
ScannedCount: 3 }
{ Items:
[ { cId: 'big' },
{ cId: 'scary' },
{ cId: 'muppet' } ],
Count: 3,
ScannedCount: 3 }
This is the object I am getting back from a function and I'm trying to access the individual items to update their values.
When I want to print 'who' for example, I do this:
console.log(obj.Items[0].mId)
Now I expect to get 'who' back, but this is what prints:
undefined
who
That 'undefined' always tags along. What am I doing wrong here?
Also, if I try to change the value somewhere by doing:
obj.Items[0].mId = 'x'
This happens:
{ Items:
[ { mId: 'x' },
{ mId: 'am' },
{ mId: 'I' } ],
Count: 3,
ScannedCount: 3 }
{ Items:
[ { cId: 'big', mId: 'x' },
{ cId: 'scary' },
{ cId: 'muppet' } ],
Count: 3,
ScannedCount: 3 }
This is not what I want.. I don't understand how to access only the first 'Items'. It seems like I'm accessing both.
Any help or advice is greatly appreciated. I probably don't need to say that I'm not very used to working with JSON.
For the undefined issue, please see the answer here: What does it mean if console.log(4) outputs undefined in Chrome Console? but TL;DR you're just seeing the 'undefined' return from console.log(), because it has no return value. It shouldn't be an issue once you're not working in the console.
As for how you have 2 separate objects both called obj, I don't understand, as other said in the comments, please post the full code so we can see how this is being used/generated.
Also for clarification it looks like you're working with JavaScript objects, not JSON, similar but not the same.

Merging MongoDB fields of documents into one document

I'm using MongoDB 2.6.6
I have these documents in a MongoDB collection and here is an example:
{ ..., "field3" : { "one" : [ ISODate("2014-03-18T05:47:33Z"),ISODate("2014-06-02T20:00:25Z") ] }, ...}
{ ..., "field3" : { "two" : [ ISODate("2014-03-18T05:47:33Z"),ISODate("2014-06-02T20:00:25Z") ] }, ...}
{ ..., "field3" : { "three" : [ ISODate("2014-03-18T05:47:39Z"),ISODate("2014-03-19T20:18:38Z") ] }, ... }
I would like the merge these documents in one field. For an example, I would like the new result to be as follows:
{ "field3", : { "all" : [ ISODate("2014-03-18T05:47:39Z"),ISODate("2014-03-19T20:18:38Z"),...... ] },}
I'm just not sure any more how to have that result!
Doesn't really leave much to go on here but you can arguably get the kind of merged result with mapReduce:
db.collection.mapReduce(
function() {
var field = this.field3;
Object.keys(field).forEach(function(key) {
field[key].forEach(function(date) {
emit( "field3", { "all": [date] } )
});
});
},
function (key,values) {
var result = { "all": [] };
values.forEach(function(value) {
value.all.forEach(function(date) {
result.all.push( date );
});
});
result.all.sort(function(a,b) { return a.valueOf()-b.valueOf() });
return result;
},
{ "out": { "inline": 1 } }
)
Which being mapReduce is not exactly in the same output format given it's own restrictions for doing things:
{
"results" : [
{
"_id" : "field3",
"value" : {
"all" : [
ISODate("2014-03-18T05:47:33Z"),
ISODate("2014-03-18T05:47:33Z"),
ISODate("2014-03-18T05:47:39Z"),
ISODate("2014-03-19T20:18:38Z"),
ISODate("2014-06-02T20:00:25Z"),
ISODate("2014-06-02T20:00:25Z")
]
}
}
],
"timeMillis" : 86,
"counts" : {
"input" : 3,
"emit" : 6,
"reduce" : 1,
"output" : 1
},
"ok" : 1
}
Since the aggregation here into a single document is fairly arbitrary you could pretty much argue that you simply take the same kind of approach in client code.
At any rate this is only going to be useful over a relatively small set of data with next to the same sort of restrictions on the client processing. More than the 16MB BSON limit for MongoDB, but certainly limited by memory to be consumed.
So I presume you would need to add a "query" argument but it's not really clear from your question. Either using mapReduce or your client code, you are basically going to need to follow this sort of process to "mash" the arrays together.
I would personally go with the client code here.

Categories