I am having trouble deleting a single item from a list. I want to delete the 'oldest' item, and these have been added via the .push() method. It seemed pretty straightforward to do this but I am having issues. For my data structure, please see below. I am sure I am just doing something dumb as this must be a common use-case.
Any ideas/feedback would be greatly appreciated.
Code:
firebase.child('articlesList').orderByChild('site').equalTo('SciShow').limitToFirst(1).once('value', function(snapshot){
// This was one try, This seems to remove the entire articleList
snapshot.ref().remove();
// I have also tried this, and this seems to do nothing at all
snapshot.forEach(function(dataSnapshot){
dataSnapshot.ref().remove();
});
});
Data Structure:
"articlesList" : {
"-Jc16JziK668LV-Sno0s" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/c8UpIJIVV4E",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=c8UpIJIVV4E&feature=youtube_gdata",
"site" : "SciShow",
"title" : "Why Isn't \"Zero G\" the Same as \"Zero Gravity\"?"
},
"-Jc16Jzkn6q41qzWw3DA" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/Wi9i8ULtk4s",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=Wi9i8ULtk4s&feature=youtube_gdata",
"site" : "SciShow",
"title" : "The Truth About Asparagus and Your Pee"
},
"-Jc16Jzkn6q41qzWw3DB" : {
"id" : "http://gdata.youtube.com/feeds/api/videos/J7IvxfcOkmM",
"index" : "SciShow",
"link" : "http://www.youtube.com/watch?v=J7IvxfcOkmM&feature=youtube_gdata",
"site" : "SciShow",
"title" : "Hottest Year Ever, and Amazing Gecko-Man Getup!"
},
The folks over at Firebase answered this for me on their Google Group. I figured I would post for others to use.
= = =
Hey Ryan,
You are close! Instead of using the value event, you want to use the child_added event. The value event will get fired once with all the data at your /articlesList/ node. That is why you are seeing it delete the whole list. If you use the child_added event, it will fire for each child. Or, if you limit it like you did, it will only fire for a subset of children. One other thing to change is to use limitToLast(1) instead of limitToFirst(1) to get the last child.
Here's the code:
firebase.child('articlesList').orderByChild('site').equalTo('SciShow').limitToLast(1).once('child_added', function(snapshot){
snapshot.ref().remove();
});
Jacob
Related
I have a document with the following structure:
{
"email" : "a#gmail.com",
"value" : 100,
"children" : [
{
"email" : "b#gmail.com",
"value" : 100
},
{
"email" : "b#gmail.com",
"value" : 200
}
]
}
I want to remove all elements with the email b#gmail.com from the children array. I am able to remove one item if I pass the whole object to be removed like this:
FieldValue.arrayRemove(childObject)
But I want both the objects with the email b#gmail.com to be removed. Is there anyway to achieve this using FieldValue.arrayRemove()?
The arrayRemove operation removes the exact item that you specify from the array. There is no way to pass a partial object and remove all array items that match the partial information. You will have to pass in each complete item that you want to remove.
If you don't know what those items are yet, you will typically have to first read the document, loop over the items in the array to remove them, and write the modified array back to the document.
As an update, it is still the case that you must match the object exactly to remove it from an array. Additionally, of course, in the example above, he is querying for a value, which requires a query to see what matches.
However, depending on the logic: if you use a Map instead...for instance in the case above, adjusted:
"children" :
"b#gmail.com_100":
{
"email" : "b#gmail.com",
"value" : 100
},
"b#gmail.com_200":
{
"email" : "b#gmail.com",
"value" : 200
}
You can simply use:
'children.b#gmail.com_200': FieldValue.delete(),
As of late, I've gravitated away from Lists to Maps for this reason.
I have something strange with a piece of code.
I have interventions and each intervention is associated to a customer. Then, in my interventions list template I use:
{{pathFor 'editCustomer' customer}} where customer is the customer _id.
If I print {{customer}} I get vFJHY2CtLi4GC7T5h but the link contains ueYXhWGL6mG3Cbq3v
ueYXhWGL6mG3Cbq3v corresponds to intervention _id
So the link is wrong beacause the id parameter is not that from the customer but the intervention
The document looks like:
{ "_id" : "ueYXhWGL6mG3Cbq3v", "title" : "intervention#1", "priority" : "medium", "customer" : "vFJHY2CtLi4GC7T5h", "assignedTo" : "97xzchCuSQGduz5vR", "issue" : "pokpokpok", "author" : "97xzchCuSQGduz5vR", "createdAt" : ISODate("2016-02-04T06:47:28.033Z") }
My router for customer id is:
Router.route('/customers/:_id', {
name: 'editCustomer',
data: function() {
return Customers.findOne(this.params._id);
}
});
An idea ?
Try to use
{{#with Customer}}
to set the data context just before
{{pathFor 'editCustomer' }}
The solution was to prefix the value with _id= like proposed by Łukasz Kapica
So: {{pathFor 'editCustomer' _id=customer}}
Thanks Łukasz Kapica
I'm new to meteor and I tried to use the tmeasday:publish-counts package to publish some counts. Reactivity works fine out of the box when I just read the counts, but when I use the counts in a Template.helper function, the function doesn't get updated when the counts change.
Here is what I have :
On the server :
Meteor.publish('counters', function() {
Counts.publish(this, 'searches-thisWeek', UserActions.find({
$and: [
{ action: SEARCHES_REGEX },
{ date : { $gte : moment().startOf('week').toDate()} },
{ date : { $lt : moment().toDate()} }
]
}));
Counts.publish(this, 'searches-lastWeek', UserActions.find({
$and: [
{ action: SEARCHES_REGEX },
{ date : { $gte : moment().subtract(1, 'week').startOf('week').toDate()} },
{ date : { $lt : moment().subtract(1, 'week').endOf('week').toDate()} }
]
}));
});
On the client :
Template.dashboard.helpers({
nbSearchesThisWeek : function() {
var variation = Counts.get('searches-thisWeek') - Counts.get('searches-lastWeek');
return {
currentValue : Counts.get('searches-thisWeek'),
orientation : {
sign: (variation > 0) ? '+' : '',
class: (variation > 0) ? 'up' : 'down'
},
variation : variation
};
}
});
In my template I have a :
<td>{{getPublishedCount 'searches'}}</td>
<td>{{#with nbSearchesThisWeek}}{{>variations }}{{/with}}</td>
It uses this subtemplate :
<template name="variations">
<div class="variation col-lg-12">
<span class="variationValue {{orientation.class}} col-lg-6">{{orientation.sign}}{{variation}}</span>
<span class="currentValue col-lg-6">{{currentValue}}</span>
</div>
</template>
The {{getPublishedCount 'searches'}} updates fine. It just gets my "searches" counter and updates anytime the counter changes.
However, the counters in the subtemplate execute fine at startup but never update when any of the dependent counters change.
So my question is, how and where do I make my nbSearchesThisWeek helper react to the changes on the dependent counters values ? I'm very confused when I read the documentation about Deps, Tracking, and ReactiveVars... I didn't really understand where those things should be used to make my use case work...
Thanks for your help.
Philippe
I have created a MeteorPad with code which is as far as possible the same as yours and it is all reactive, without any changes to your code.
Please note that instead of trying to recreate your UserActions collection, I have created two separate collections, UserActions and Players (the names have no significance) to create two counters just like yours. I think once you have seen the code you will agree that for the purpose of checking your code it will do.
Go to this page: http://app-cmrd2ous.meteorpad.com/ open the Chrome or Firefox console and insert the following two records and watch the counters:
UserActions.insert({name: 'bloggs', date: new Date()});
Players.insert({name: 'bloggs again', date: new Date()});
The counters are all reactive.
The meteorpad is here: http://meteorpad.com/pad/n4GwwtPesEZ9rTSuq/Dashboard
All I can suggest is that you look at where I have put the code (whether on the client or the server) - maybe that has something to do with it.
But maybe more likely is that you were running the wrong tests. In other words perhaps you got your dates wrong - you thought you were inserting a record with a date for last week, whereas actually it was two weeks ago or something like that.
I need to get the PHIDs for one project and several users in our Phabricator install. It seems like it should be trivial to find out how to do this, but I've searched the docs to no avail. Am I looking in the wrong place or something?
Easiest way:
Go to the project
Click New Task
Look at the URL, it will have a parameter like:
?projects=PHID-PROJ-owipizovyry4fatifwfd
PHID is "PHID-PROJ-owipizovyry4fatifwfd"
Option 2:
Go to your Conduit [phabricator_url]\conduit
Find the method project.query
Enter the name in a JSON encoded array (i.e. ["project name"])
Click Call Method
PHID will be one of the data elements:
{
"data" : {
"PHID-PROJ-oybqquyhhke4awiw2akz" : {
"id" : "19",
"phid" : "PHID-PROJ-oybqquyhhke4awiw2akz",
"name" : "project name",
"members" : [
"PHID-USER-gapak5h34h6d5yvl67dx",
"PHID-USER-674vq754zfuhyxgvvq7x",
"PHID-USER-qvcdsyc4oz7rzpzziiyk",
"PHID-USER-qmefzjtsrmnxjxpc45km",
"PHID-USER-pbhygge7rgpdowz3s5vk"
],
"slugs" : [
"project_name"
],
"dateCreated" : "1396666703",
"dateModified" : "1396668261"
}
}
}
A more robust method would be to call the conduit method phid.lookup:
https://<your install>/conduit/method/phid.lookup/
Then enter in names something like #user, #project or Z2 and you'll get the PHID.
I realize that this might be very close to other posts, but I just can't get this to stick in my head! :( I need some help in trying to understand how to use .find() or should I be using .findOne()? (so confused) for a collection of mine.
Goal:
I want to get all of the documents out of the People collection and then for each document I want to create a new <option> where the .name is put in for text and the collection ._id is the value.
Here's some code:
The Collection results from Mongo
db.people.find()
{ "_id" : "1", "name" : "John" }
{ "_id" : "2", "name" : "Mike" }
{ "_id" : "3", "name" : "George" }
{ "_id" : "4", "name" : "Jane" }
My Template Helper :
Template.view_Admin_Staff.people = function() {
console.log( 'people : ', People.find() );
return People.find();
};
My Template :
<select id="ddStaffID" name="staff">
<option value="">-- Select One --</option>
{{#each people}}
<option value="{{_id}}">{{name}}</option>
{{/each}}
</select>
My console.log found in the Helper returns undefined. What in the world am I missing?
I am going to assume that your collection is People = new Meteor.Collectin('people'); And your template name for in the html is
When you did the console log in your template helper, you are logging the cursor itself, not the documents. You can find out more about cursor at (https://www.eventedmind.com/tracks/feed-archive/how-do-client-cursors-work).
To see are you returning the correct data, you could .fetch method on a cursor. Fetch will return an array of objects based on your query. In your case, the query is empty, the fetch method should return everything that is available in the client's db.
To answer your question in the title. both find and findOne are methods available on the Collection object.
find return a cursor. findOne return AN object, if there is a record matched to your query.
Bloody-h3ll! Warning to all us n00bs out there...one must subscribe to your publications in order for one to see and work with your publications. sigh
The code in my initial post is working as expected. I just simply forgot to subscribe to my exposing data in my publication in my client-side route. </foreheadSlap> I'm new enough to have doubted my query skills and didn't even thing to troubleshoot any further back in the code. Thank you #Bozhao and #DavidWeldon for your quick replies.