While working with Firebase (the realtime database) I'd like to know the following about the objects in the database:
Whether an object exists at a path
When an object is created at a path
When an object is destroyed at a path
I can figure out some hacks for these. For example:
Subscribe to on('value') events and download the whole (often huge) object.
Create a separate "flag" value for each object in the database that gets modified when objects are created and destroyed.
Listen for 'child_added', 'child_removed', etc. on a particular field inside of an object, that has the same lifetime as the object.
These get the job done in some specific circumstances but are pretty arbitrary and don't scale well.
Is there a way to achieve the above without having to either download the whole object or else creating a bunch of "book-keeping" entries in the database?
It's common to duplicate data and add additional to your database to satisfy your expected queries, without accessing too much data. There aren't any hidden or secret operations - what you see in the documentation is your toolset. It sounds like you're doing the right things already.
Assuming the web SDK (browser perspective), realtime updates (.on) are the proper way to get this type of data. The data should not be huge - it's called the "Realtime Database" bcs it's not intended to store large filetypes such as images and videos.
Listen for value events
var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', function(snapshot) {
updateStarCount(postElement, snapshot.val());
});
Related
I have a firestore collection with a bunch of documents, each with plenty subfields. On a web page I need a list of a specific subfields from each document.
Currently I load the the entire database when you load the page and then loop through and get the wanted values. This uses way to many reads to get very little data.
Is there a way to solve this e.g. a autogenerated a collection that contains field from other collection in an array or something.
Many thanks in advance
Auto-creating such a subcollection with just the fields you need is a great way to reduce the bandwidth needed to load the data.
There is nothing built into Firestore to create those derived documents, but it's fairly easy to build something using Cloud Functions. Create a function that responds to a Firestore onWrite trigger, and write the subset of the data to its destination there. It's common to have a separate Cloud Function for each such use-case, and I regularly see projects with 100+ such functions.
I expect we'll also start seeing Firebase Extensions for this type of thing, but right now no-one seems to have built one.
I want to read data from firebase, in the ref ("locations/{{someLocation}}/logs/{{someDevice}}")
but I do not know if exists a correct form to do, because I need to use ".on" to hear constantly all the devices changes, the problem is that I need to read all devices in logs in all locations, but I do not want another information, I just need information in logs or in the specific device, I know that I could reach that invoking one callback ".on" for each device, but I want a cleaner form to make it and in the documentation, there is no help for this.
maybe I could invoke a method like that
firebase.database("locations/{eachLocation}/logs/{eachDevice}").ref().on...
because I do not want all the devices, the problem is that I do not know if there is a form to make it thank you.
It sounds like you've nested your data too much. The Firebase documentation has explicit sections on avoiding nesting data and flattening data structures with hints on how to prevent this.
At first glance you'll need at least two top-level lists: locations and locationLogs. Under each you have the same keys as you have now, but the logs are now under /locationLogs/$key instead of under /locations/$key/logs. With that change you can get the logs for a location without getting the other data for that location.
If you don't know the location key, but don't want to get the logs for all locations, it sounds like you've nested another level too deep. Firebase queries work on a flat list of nodes, and can't search across multiple levels of unknown keys. If you want to search across all logs across all locations, you will need to keep a flat list of all logs. You can then tie each log back to its location, by adding the location ID to each log.
So that might lead to a structure of:
logs: {
"adjustableLight....1": {
locationId: "DTZB35",
date: 156...,"
...
}
}
What you're trying to do isn't supported by Realtime Database. There are no wildcard queries or placeholders. You must be able to build the full path to the node whose data you want to get.
Consider changing the structure of your data so that you can more easily find the nodes you want. It is common in nosql type databases to duplicate data into structures that are easier to query for a particular use case.
For a project in my uni, I wanted to build a website that contained 200 messages and make it so that users can modify those messages, and then any other user who looks at the site would be able to see the modified messages and modify messages themselves. There would be exactly 200 messages, and the only way to make a new one is to override an existing one.
I've got all the user interface stuff functional and I've been tinkering with using the Google Sheets API to accomplish the string storage since it will handle JS arrays, but it doesn't seem to really be built for this type of use case.
If it would be possible to store the messages as strings (maybe in an array) in a document on the server and be able to use the javascript to make permanent adjustments to the strings in that document it would be amazing but I can't seem to find any sort of documentation on how to do something like that.
Does anyone know of any methods to approach a problem like this using JS and Jquery? Or know of an API they can recommend would be amazing.
Basically what I have already is a system that would call up the complete list of messages and store that as an array of strings.
var messagesIndex = (some sort of get function);
Then the user can select a message, and modify it, at which point the locally stored array is updated.
active = "(this is just here to make it a global var, it's just an index of which message I want from the array of messages)"
$(function() { $("button").click(function() {
active = this.id;
update();
});
});
function update(){
//sets the message inside the message display box to the correct message, where it can be altered
$("#message").messagesIndex[active]);
//some other stuff here that isnt relevent to this question.
}
and then the java would send that updated set of strings which would permanently override it in that storage doc. At least that would be my ideal situation.
I wanna pull whole data from the firebase database and access that without change data.
firebase.database().ref(‘someBigNode’).once(‘value’, (snapshot) => {
//do something
}
But it will cost many memory.
May I ask how to pull whole data partially and save memory?
When you read data from Firebase Database with the JavaScript (or iOS or Android) SDK, it will always read complete nodes. So the only way to retrieve less data is to retrieve a node lower in the JSON tree.
If you find you need to retrieve a part of each node under someBigNode, you should split that part of each node out into a top-level node of their own importantBitsOfSomeBigNode.
It's unfortunately hard to be more helpful without a more concrete example of your data structure and the bits you're trying to retrieve (and the reason why those bits are special).
I'm using Meteor JS for a project so inherently I'm using MongoDB. I'm storing a user's check in and out actions. I'm currently storing them as individual docs in the collection. Each action contains 3 fields; in or out, time of action and userid. Is the best way to go though? Should I just have one doc per members and then store each action in an array? Is there another way? I anticipate several hundred members, but hopefully several thousands of members in the future. Thanks.
From experience, I can say that storing records instead of arrays is a better choice in the long run.
As far as Meteor is concerned, its reactivity handles collection records, but not individual fields in arrays. In other words, if one element gets added to the checkins array of a user object, the entire user object needs to be synchronized with the clients. If you store records instead, only the newly added record will be sent by the publication.
As far as MongoDB is concerned, there is a document size limit of 16MB. Not sure how frequent your checkins and checkouts are, but if you store them in an array, you might run into that limitation at some point.
Records are also easier to access than arrays.
For more details, see MongoDB data modeling and Database modeling in Bulletproof Meteor.