Firebase: myDataRef.push() - controlling node names - dont like this: '-Ivpzk1cIzxb6ETuZuxw' - firebase

I am looking for a way to control the 'node names' in firebase
I have to push an json-String into the firebase db like:
myDataRef.push(<?php print $item->as_json(true); ?>);
myDataRef.push({"TEST": <?php print $item->as_json(true); ?>, ".priority": 1.0});
Question:
How can I modify this 'node names':
-Ivpzk1cIzxa6ETuZuxw
Thanks for any helpful suggestions

If you'd like to control names, use set instead:
var myDataRef = new Firebase("https://<your-firebase>.firebaseio.com/TEST");
myDataRef.set(<?php print $item->as_json(true); ?>);
push is meant to autogenerate IDs that have the timestamp encoded in them and are therefore chronologically ordered. You usually don't need to use priorities with push-generated IDs since they're already ordered lexicographically.

Related

How to use startAt() in Firebase query?

Let's suppose above firebase database schema.
What I want to is retrieve messages which after "15039996197" timestamp. Each of message object has a createdAt property.
How can I get messages only after specific timestamp? In this case, last two messages are what I want to retrieve.
I tried firebaseb.database().ref(`/rooms/$roomKey/messages`).startAt('15039996197') but failed. It return 0. How can I do this?
The case with your query is that it's expecting that the message node should have a number value to start with, in that case you want a child node with the name createdAt. So in that case you must specify that you want to order by createdAt, thus you need to do this
firebase.database().ref(`/rooms/$roomKey/messages`).orderByChild('createdAt').startAt('15039996197').on(//code);
This way it'll return all nodes inside message that has a child named createdAt an it starts at 15039996197. Ordering your query may be a little bad for performance, for that i sugest taking a look at .indexOn rule.
For more information take a look here.
Hope this helps.
Firebase Data Retrieval works node by node.
So whatever data you want to get, the entire node is traversed.
So in your case to get any message your complexity would be O(number of messages).
You would want to restructure the way you are storing the data and put createdAt in Node instead of Child.
If your database structure looks like that, you can use:
firebase.database()
.ref(`/rooms/$roomKey/messages`)
.orderByChild('createdAt')
.startAt('15039996197').on('value', snapshot => { /* your code here */ });
But if you work with a lot of data entries, you can also name the item key with the timestamp, instead of storing the timestamp in your data. This saves a little data on your database.
firebase.database().ref(`${rooms}/${roomKey}/${timestamp}`).set("value");
To retrieve the data in that case instead of orderByChild('createdAt'), you'll use orderByKey(). Because firebase keys are of the string type, you need to make shure to parse the timestamp in the .startAt() to a string.
It will then look something like this:
firebase.database()
.ref(`/rooms/$roomKey/messages`)
.orderByKey()
.startAt(`${15039996197}`).on('value', snapshot => { /* your code here */ });
You can do something like that:
firebase.database().ref('/rooms/$roomKey/messages')
.orderByChild('createdAt')
.startAt('150399')
.endAt('1503999\uf8ff')
.on('value', function (snapshot) {
var key = snapshot.key,
data = snapshot.val();
console.log(key + ': ' + JSON.stringify(data))
});
Be sure to set endAt().

How to parse a collection's sub-object to find a unique result from many possibilities?

In my user's schema, I have a TokAuth Array with token sub-objects (like multiple mails addresses).
So in a method, when I search the tokens in the current user :
var id = Meteor.userId();
var usercurrent = Meteor.users.findOne({_id: id}, {fields: {"TokAuth": 1}});
var userToken = usercurrent.TokAuth.token;
I got in console.log(userToken)
[ 'fyAyXkXYrQdAlNpjuQfJ8RLU2TpfVGLnptlBs-m1h7xk',
I20170224-20:36:23.202(1)? 'YTwtUbhNTgiEfzFbJq7mESnOoOHeLYxWlqEeJJIG_GiV',
I20170224-20:36:23.206(1)? 'ViA4ydDITJtHDi2c_sArkNtpRYTjFqGL1ju2v00_-rFJ',
I20170224-20:36:23.206(1)? '51ImZcxRADLJr-FPCUL7EFGnTZYjHSZk3XxdqtBV2_fd',
I20170224-20:36:23.207(1)? 'S5aEvqjJ5zTUJqLFCPY1aZ1ZhsQppZTJtYKULM9aS2B3',
I20170224-20:36:23.207(1)? 'mhBs3oxHf2SxZfu2vCZhtiyPfg25fKMY8bKMZD8fx6IG',
I20170224-20:36:23.207(1)? '-rv0FiP-lxoqe8INyCJASV6rZpbgy3euEqB9sO9HsZSV',
I20170224-20:36:23.207(1)? 'zacr6_VBjHTsArov1LmQyZFLwI40fx4J7sygpLosTrli' ]
Beside, I've got a var who is equal to the last token in the userToken sub-object (that's of course expected : not to be the last one, but to be in the sub-object).
console.log (editAuth);
zacr6_VBjHTsArov1LmQyZFLwI40fx4J7sygpLosTrli
So how can I parse userToken to find a match with editAuth? If userToken was just a String, it will be simple but here...
Thanks
Is there a reason you are storing all the tokens as an array as opposed to just updating a single string each time?
That aside, you can check if an array contains a value by using the handy underscore function _.contains
Example:
_.contains( userToken, editAuth ); //returns true or false
In this case, you are simply trying to search for a string within an array of strings. #Sean already provided one solution.
If you are using the meteor ecmascript package then you can just simply use the native Array.includes method.
userToken.includes(editAuth);
On a side note, after using ECMAScript 2015+ for some time now, I find that I can use the native API for almost everything that I used to use underscore or lodash for. Check it out!

AngularFire NormalizedCollection and order in firebasearray

I use AngularFire and Firebase-util library.
I would like to order a list in descending order from the last element to the first insert (in the bottom of this list).
var ref = firebase.database().ref();
var nc = new firebase.util.NormalizedCollection(
ref.child('demandes/'+$state.params.chatId+'/reponses'), // main path
[ref.child('reponses'), 'widget2'] // second path
).select('widget2.timestamp_inverse', 'widget2.intitule', 'widget2.commentaires', 'widget2.prix')
.ref();
$scope.reponses = $firebaseArray(nc);
I saw that to order depends on the main path ! But this main path is just a list of Firebase keys like -AZE4AZ4RQ4F53.
How can I order this list like I want please ? Server-side or Client-side if needed ...
I think I'm forced to proceed like that : client-side
With firebasearray, don't use track by $index or it will display an error like "expected array but received ..." and filter & order your array like you want :
<ion-item ng-repeat="reponse in filteredItems = reponses | orderBy:'FIELD_CHOSEN':true ">
If you have any suggestions to descending sort server-side, It will be nice to share with me :) Thank you

Meteor.js: Find all documents and return in reverse natural order

I am trying to return all documents in a collection, to use it with an {{#each}} in my template. My code looks like this:
return Answers.find({}, {sort: {$natural:-1}})
But the documents are returned in natural order (not reverse). Does anyone know why? I got the $natural selector from the MongoDB documentation, so I don't see what's wrong.
Can't tell why don't it returns in reverse order.
But you can create an array in the template helper method and return reverse of an array using array.sort() or array.reverse() functions.
For ex: Say you Answers collection looks like this:
Answers({ansNo: 1, ansBody: "body1"},
{ansNo: 2, ansBody: "body2"},
{ansNo: 3, ansBody: "body3"});
And the array to be returned is:
var AnswersArr = new Array();
then in your template helper :->
var tempCollection = Answers.find({});
tempCollection.forEach(function(data){
var obj = {ansNo: data.asnNo, ansBody: data.ansBody};
AnswersArr.push(abj);
});
AnswersArr.sort(function(a, b){return b.ansNo - a.ansNo;}); //sort in reverse order
return AnswersArr;
Sort isn't a parameter but a separate function to be called after find() on the resulting Cursor object. This is the method that the MongoDB documentation is referring to and works with drivers such as MongoJS:
return Answers.find().sort({$natural: -1});
It seems Meteor hasn't added the sort() function to their implementation of Cursor, so an alternate solution would be to sort by the _id field which is generated based on date (and hence insertion order):
return Answers.find({}, {sort: {'_id': -1}});
As a workaround you could do this:
return Answers.find().fetch().reverse();
I know it would be nicer to do it via the sort parameter, but I don't think it's possible right now.
I think you might be confusing definitions of 'natural order' here. One the one hand there is a natural sort order for letters/strings (A,B,C...) and numbers (1,2,3...).
But in the case of mongo, 'natural' refers to the order the data was written to disk. '{$natural:1}' returns 'documents in the order they exist on disk...' and, so '{$natural:-1}' reverses that (http://docs.mongodb.org/manual/reference/operator/meta/natural/).
So without the code that writes the data and some insight into how it was written to disk, we cannot test your hypothesis that it is not working correctly.

Get Meteor collection by name

Suppose I write:
new Meteor.Collection("foos");
new Meteor.Collection("bars");
Is there an API for accessing those collections by name? Something like Meteor.Collection.get(name), where name is "foos" or "bars"? I know I could write something like
var MyCollections = {
foos: new Meteor.Collection("foos");
bars: new Meteor.Collection("bars");
}
and then use MyCollections[name], but I'd prefer to use an existing API if one exists.
Based on Shane Donelley's mongoinspector
https://github.com/shanedonnelly1/mongoinspector
getCollection = function (string) {
for (var globalObject in window) {
if (window[globalObject] instanceof Meteor.Collection) {
if (globalObject === string) {
return (window[globalObject]);
break;
};
}
}
return undefined; // if none of the collections match
};
I've just found that package : https://github.com/dburles/mongo-collection-instances/
It allow you to
Foo1 = new Mongo.Collection('foo'); // local
Foo2 = new Mongo.Collection('foo', { connection: connection });
Mongo.Collection.get('foo') // returns instance of Foo1
Mongo.Collection.get('foo', { connection: connection });
// returns instance of Foo2
Hope it will help
This feature was added to Meteor in Feb 2016: "Provide a way to access collections from stores on the client"
It works like this:
Meteor.connection._stores['tasks']._getCollection();
And I was using it as follows to test inserts using the javascript console:
Meteor.connection._stores['tasks']._getCollection().insert({text:'test'});
For the insert it required the insecure package to still be installed otherwise got an access denied message.
As far as I can see in the collection.js source there currently is no way in the api to get an existing Collection by name, once it has already been initialized on the server. It probably wouldn't be hard to add that feature.
So, why not fork Meteor and submit a patch or create a smart package and share it I'm sure there are others out there who'd like the same feature.
With https://github.com/dburles/mongo-collection-instances you can use Mongo.Collection.get('collectionname')
Note that the parameter you're inserting is the same one you use when creating the collection. So if you're using const Products = new Mongo.Collection('products') then you should use get('products') (lowercase).
Note that they have a return value, so you can just do
var Patterns = new Meteor.Collection("patterns");
and use Patterns everywhere.
And when you need to subscribe to server updates, provide "patterns" to Meteor.subscribe().
If you have the same code for multiple collections, the chance is high that you're doing something wrong from a software engineering viewpoint; why not use a single collection with a type field (or something else that differentiates the documents) and use that instead of using multiple collections?
Rather than looking, I've just been doing:
Foos = new Meteor.Collection("foos");
or possibly put it inside another object. I haven't really been making a Collections collection object.
It seems there is no way to get at the wrapped Meteor.Collection object without saving it at creation time, as others have mentioned.
But there is at least a way to list all created collections, and actually access the corresponding Mongo LocalCollection object. They are available from any Meteor Collection object, so to keep it generalistic you can create a dummy collection just for this. Use a method as such (CoffeeScript):
dummy = new Meteor.Collection 'dummy'
getCollection = (name) ->
dummy._driver.collections[name]
These objects do have all the find, findOne, update et al methods, and even some that Meteor doesn't seem to expose, like pauseObservers and resumeObservers which seem interesting. But I haven't tried fiddling with this mongo LocalCollection reference directly to knowif it will update the server collection accordingly.
var bars = new Meteor.Collection("foos");
Judging by what the collection.js does, the line we use to instantiate the collection object opens a connection to the database and looks for the collection matching the name we give. So in this case a connection is made and the collection 'foos' is bound to the Meteor.Collection object 'bars'. See collection.js AND remote_collection_driver.js within the mongo-livedata package.
As is the way with MongoDB, whilst you can, you don't have to explicitly create collections. As stated in the MongoDB documentation:
A collection is created when the first document is inserted.
So, I think what you're after is what you already have - unless I've totally misunderstood what you're intentions are.
You can always roll your own automatic collection getter.
Say you have a couple of collections called "Businesses" and "Clients". Put a reference each into some "collections" object and register a Handlebars helper to access those "collections" by collections["name"].
i.e. put something like this on the client-side main.js:
collections = collections || {};
collections.Businesses = Businesses;
collections.Clients = Clients;
Handlebars.registerHelper("getCollection", function(coll) {
return collections[coll].find();
});
Then in your HTML, just refer to the collection by name:
{{#each getCollection 'Businesses'}}
<div> Business: {{_id}} </div>
{{/each}}
{{#each getCollection 'Clients'}}
<div> Client: {{_id}} </div>
{{/each}}
Look ma, no more generic "list all records" boilerplate js required!

Resources