Update A Firebase node with a Snapshot data without overwriting Data - firebase

I'm looking at synching a node e.g. /a/b/c with node /data/c
There is data at node /a/b/c - so I just want to grab a snapshot of /data/c and put that data in to /a/b/c without deleting existing values.
Would an approach like :
Ref.update({
snapshotdata.val()
}).key;
Would this work? I'm not sure how firebase would parse the snapshot, if it takes the whole thing and overwrites or it would take individual values and adds.
Thanks in advance for any clarity.
Best Regards,
Kieran

It depends. Snapshot values are simply JSON objects (or primitives, depending on the node). update() will replace any nodes specified by the keys in the update, but not any that aren't. So if /a/b/c looks like:
{
name: 'old name',
data: {
gonnabe: 'gone'
},
created: 12345679
}
and data/c looks like:
{
name: 'new name',
data: {
nested: true
},
updated: 12345679
}
doing an db.ref('a/b/c').update(dataSnapshot.val()) will result in:
{
name: 'new name',
data: {
nested: true
},
created: 12345679,
updated: 12345679
}
Note that the nested field in data was wiped out by the update, but the non-nested field created was not.
If you want to do deep updates, you'll need to construct an update with slash-delimited fields for each deep node you want to update. So instead of the above, you might have:
{
"name": "new name",
"data/nested": true,
"updated" 12345679
}
This will be non-destructive to the nested data and only update values that are directly referenced, resulting in:
{
name: 'new name',
data: {
gonnabe: 'gone',
nested: true
},
created: 12345679,
updated: 12345679
}
Hope that helps!

Related

Deleting all files in a firebase folder?

The Firebase documentation on deleting data says:
Delete data
The simplest way to delete data is to call remove() on a reference to the location of that data.
You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call.
can anybody explain to me what they mean by the last line I think is could help me delete all files in a firebase folder?
In Firebase:
dataRef.remove() is strictly equivalent to dataRef.set(null)
dataRef.child('foo').remove() is strictly equivalent to dataRef.update({ foo: null })
That means that setting or updating to null will effectively remove the property.
Updates can be used for removing multiple properties in that way:
Consider this example Firebase Object:
exampleData = {
foo: 'anyValue',
bar: 'otherValue',
baz: {
aProp: true,
anotherProp: false
}
}
The following
db.ref('/exampleData').update( { bar: null, 'baz/aProp': null })
will result in the following object:
exampleData = {
foo: 'anyValue',
baz: {
anotherProp: false
}
}
So you can use one update instead of multiple remove (or set) to delete several properties.
If you have this in your database:
users: {
user9266622: {
id: 9266622,
name: "SylvainC"
},
user209103: {
id: 209103,
name: "Frank van Puffelen"
}
}
Then you can delete a specific property with something like:
firebase.database().ref("/users/user209103/name").remove();
You can remove an entire branch by calling remove() on the top of that branch. So to remove "my" entire profile:
firebase.database().ref("/users/user209103").remove();
I think this last snippet is what you're looking for: it removes /users/user209103 and everything under it.
The last line of the documentation you quote is about updating/removing multiple branches/properties in distinct locations in one call. For example, say you want to remove the id property from both profiles (since they're redundant). You can do this with:
firebase.database().ref().update({
"/users/user9266622/id": null,
"/users/user209103/id": null
});
This is called a multi-location update, since you're updating two locations by their full path.

Best way to make ReactiveAggregate reactive when data changes on a user

I am currently using ReactiveAggregate to find a subset of Product data, like this:
ReactiveAggregate(this, Products, [
{ $match: {}},
{ $project: {
title: true,
image: true,
variants: {
$filter: {
input: "$variants",
as: "variant",
cond: {
$setIsSubset: [['$$variant.id'], user.variantFollowing]
}
}
}
}}
], { clientCollection: 'aggregateVariants' }
As you can see, a variant is returned if user.variantFollowing matches. When a user 'follows' a product, the ID is added to their object. However, if I understand correctly, this is not triggering ReactiveAggregate to get the new subset when this happens. Only on a full page refresh do I get the correct (latest) data.
Is this the correct way to approach this?
I could store the user's ID as part of the Product object, but the way this would be stored would be nested two places, and I think I would need the Mongo 3.5 updates to then be able to accurately update this. So i'm looking for how to do this in Meteor 1.5+ / Mongo 3.2.12
So, I've been able to get there by adding autorun to the subscription of the aggregate collection, like this:
Template.followedProducts.onCreated(function() {
Meteor.subscribe('products');
this.autorun(() => {
Meteor.subscribe('productsFollowed');
});
... rest of function
For context, productsFollowed is the subscription to retrieve aggregateVariants from the original question.
Thanks to robfallows in this post: https://forums.meteor.com/t/when-and-how-to-use-this-autorun/26075/6

Firebase :: Best way to structure this data

im trying to use firebase to store and retrieve data for my application.. i know that it is recommended to denormalize data and that it may require data replication..
my scenario is as follows:
there are a number of users in the system..
there are a number of posts in the system..
any user should be able to get a list of posts for a particular user..
each posts has a number of users as participants..
i am tempted to use the following structure for this:
users: {
abc: {
name: 'UserA',
profilePicture: 'imageA.png'
},
pqr: {
name: 'UserB',
profilePicture: 'imageB.png'
},
xyz: {
name: 'UserC',
profilePicture: 'imageC.png'
},
...,
...,
...
},
posts: {
def: {
title: 'PostA',
users: {
abc: true,
def: true,
ghi: true,
...,
...,
...
}
},
stu: {
title: 'PostB',
users: {
abc: true,
xyz: true,
...,
...,
...
}
},
...,
...,
...
}
the issue with this is that if i need to show a list of users with each post, i will need to make a query to POST, and then make sequential calls to USER for each user inside that post to get the name/profilePicture data..
if i replicate the user info inside posts as well, the issue becomes that if a user later changes her profilePicture or name, then existing posts will still show the old data..
how can i structure this data better so these cases are efficient?
thanks..
Don't replicate data inside posts. Read Firebase Docs about structuring data
Best practices:
Avoid nesting data
Flatten data structures
if you include data in post you are breaking those 2 rules (and you don't want it).
Multiple calls are not bad.

How to create AutoForm field in Meteor to select a record from another collection and save it as a subdocument?

I've been struggling with this for a couple of hours and I can't find a good solution so maybe someone can shed a light on this.
I have a simple schema like this:
var groupschema = new SimpleSchema({
name: {
label: 'Name',
type: String
},
description: {
label: 'Description',
type: String
}
}
And I have another one:
var itemschema = new SimpleSchema({
name: {
label: 'Type:',
type: String
},
details: {
label: 'Details',
type: String
},
group: [groupschema] // <--- this is my main interest
}
If I use the above code sample AutoForm will generate an "inner form" which is quite cool actually for some puporse (e.g. for a contact to have an array of adresses or phone numbers) but for me I would like a drop-down select with the name of the group and when I click on the Insert/Update button (depending on the current form) I would like to add the whole group document to the inserted/updated item document as a subdocument.
Something like this will be inserted to the mongodb:
{
_id: the generated mongoid,
name: "This is a type",
details: "There are some thing to know about this type",
group:{
name: "Cool group",
description: "This is a really cool group"
}
}
The actual documents are far more complicated the above example is just an oversimplified version.
I've stopped writing this question yesterday and tried to do my own version.
My - half baked - solution is:
introducing a new field in the schema named groupselect (type string, autoform type: select)
populate it's contents with a Collection.find().map() lookup
groupselect: {
type: String,
label: 'Group',
optional: true,
blackbox: true,
autoform:{
type: "select",
options : function() {
return Issuegroup.find().map(function (c) {
return {label: c.name , value: c._id};
});
}
}
},
using autoform hooks before insert I assign the subdocument to the real fiel group = Group.find({_id:doc.groupselect}) and I remove the helper field from the doc
using the same technique in the before update hook also for an update form
The problem I seem to be unable to solve in a clean way is to set the default value of the helper field 'groupselect' when the update form displays. I've tried the docToForm hooks but no luck.
Isn't this somehow a very common problem? I imagine there has to be a proper solution for this so I bet that I am missing something very obvious and hopefully someone will point it out for me.
Thanks

Meteor update a Collection object

in Meteor, I'm having a collection with a Schema, and a number of items are added dynamically.
In this case, I'm dealing with milestones object, and once the user check one off I want to update complete in this Collections item to true (default is false)
Here is my schema
milestones: {
type: Array,
optional: true
},
'milestones.$': {
type: Object
},
'milestones.$.name': {
type: String
},
'milestones.$.hours': {
type: Number
},
'milestones.$.complete': {
type: Boolean
}
How do I write a $set statement for this?
You have an array of objects so, $elemMatch do the trick here.
Projects.update({_id:this._id},{milestones:{$elemMatch:{'milestones.$‌​.name':this.name}},{$set:{'milestone.$.complete':value}}})
So thanks to Aldeed I found a solution - which needs to be called on server side, otherwise it won't let the update happen. Do:
Projects.update({_id:currentPostId, 'milestones.name':name}, {$set:{'milestones.$.complete':true}});
The function is called on the client with Meteor.call with all needed params.
According to your schema you have an object containing an array of objects. So you should write you $set like this:
{$set: {'milestone.$.complete':value}}
This will update the first array element corresponding to the query.
You can find here the official documentation if you want to know more about arrays updates in Mongo.

Resources