Write single value on firebase database without deleting the existing ones - firebase

I'am trying to add a single value my database without deleting the existing ones because I need them all. The structure is something like that /user/fav_post/{post_id_1,post_id_2,...}. The "fav_post" initially is empty and as the time goes by the user adds more fav_posts.
One way that solves this problem is downloading all favorite posts, putting them in a HashMap, add the new post and the push them to the database but this does not seem very optimal.
So what I am trying to achieve is to have all the favorite posts and to display them to the user.
mDatabase.child("USERS")
.child(currentUser.getUid())
.child("favorites")
.setValue(postID);
Edit: The end result should be like
Ther end result I want to be like that
root
-User
--FavPosts
---postID1(String)
And when the user favorites another post the result should be like that:
root
-User
--FavPosts
---postID1(String)
---postID2(String)

What you're looking for is a set: an unordered collection of unique values. In the Firebase Database you'd store the post Id as a key and (since Firebase doesn't allow you to store a key without a value) true as the value.
So:
root: {
User: {
FavPosts: {
postID1: true,
postID2: true
}
}
}
You'd set these values with:
mDatabase.child("USERS")
.child(currentUser.getUid())
.child("favorites")
.child(postID)
.setValue(true);

setValue() will overwrite the entire contents of the location. If you want to just add or update child values, use updateChildren() instead.

Related

Is there a way to reduce time complexity on the frontend with using Drupal json-api includes?

I'm currently working with an output from the Drupal json-api module and have noticed that the structure of an output forces an O(n^2) time complexity issue on the front by forcing the front end developers to reformat the json output given to them so an attachment can me in the same object as the entity it belongs to.
Example
So let's say I'm listing a bunch of categories with their thumbnails to be used on the front end. What a json output would normally look like for that is something like:
Normal category json structure
[
{
"uid":123,
"category_name":"cars",
"slug":"cars",
"thumbnail":"example.com/cars.jpg"
},
{
"uid":124,
"category_name":"sports",
"slug":"sports",
"thumbnail":"example.com/sports.jpg"
}
]
With drupal it seems that thumbnails are in their own includes separate from data creating an O(n^2). For example:
I make a get request using this endpoint:
example.com/jsonapi/taxonomy_term/genre?fields[taxonomy_term--genre]=name,path,field_genre_image,vid&include=field_genre_image
The structure of the data returned from the drupal json api module is going to be similar to this:
pseudo code for better readability
{
"data":[
{
"uid":123,
"category_name":"cars",
"slug":"cars",
"relationships":{
"thumbnail":{
"id":123
}
}
},
{
"uid":124,
"category_name":"sports",
"slug":"sports",
"relationships":{
"thumbnail":{
"id":124
}
}
}
],
"included":[
{
"type":"file",
"id":123,
"path":"example.com/cars.jpg"
},
{
"type":"file",
"id":124,
"path":"example.com/sports.jpg"
}
]
}
The problem with the drupal output is that I have to loop through the data and then in the data loop loop through the includes and attach each thumbnail to the category causing an O(n^2) on the frontend.
Is there a way for the frontend to request a category using the drupal json module to contain the thumbnail in the category like the normal json output above without having to restructure the json api on the frontend?
Please note I am not a drupal developer so the terminology I might use will be off.
JSON:API can output a list of entities and includes another list of entities (can have different types). each entity has UUID, so, accessing them can be O(logn) or even O(0) if you apply index to their UUID
So, you would have one loop to parse each of the included entity and store and index them (like SQLite), or simply loop over all included entities, build 1 array key by UUID and value is object of an entity

firebase doesn't showing realtime data inserting and not able to remove data [duplicate]

Read-only & non-realtime mode activated to improve browser performance
Message pops up in my project and I'm unable to delete the nodes as well
Also I read this https://groups.google.com/forum/#!topic/firebase-talk/qLxZCI8i47s
Which states :
If you have a lot of nodes in your Firebase (say thousands), we need to create a new element for each node and modern browsers simply have limitations of how many DOM elements you can add to a page
It says:
To resolve this problem, don't load your Firebase Dashboard at the root of your Firebase, but instead load it lower down in the hierarchy
I do not get what it means
How do I get back to my Realtime Dashboard?
If you want to delete a high level node when this is activated, I recommend doing this.
Open up a text editor and type in { }. Save this file as "blankJSON.json".
Go to high level node you want deleted and select it, once it opens up and shows you all the nodes that need to be removed, select the three bars at the top right and select "Import JSON", (It would be safe to first "Export JSON" If you don't have backups, in case you make a mistake here). Import the JSON file we created earlier titled "blankJSON".
This will delete all of the data inside.
Once again, I highly suggest you make a backup before doing this, It's extremely easy to make a backup and also it is much easier than you would think to upload this blankJSON to the wrong node and then erasing a bunch of important data.
When it detects that it's downloading too many nodes from your database, the Firebase Console stops using real-time mode and switches to read-only mode. In this mode it requires less work from the browser, so it is more likely that the browser will stay performant.
To get back to realtime mode, you have to go to a location that has fewer nodes. So say that you start loading the database at the root, that means that "pseudo address bar" at the top of the data tree will say:
https://<your-project>.firebaseio.com/
And then will show the list of items. Now click on the URL in that pseudo address bar and change it to:
https://<your-project>.firebaseio.com/<one-of-your-keys>
And hit enter. The data tree will reload with just the node from one-of-your-keys and down and will likely switch to realtime mode again.
Every node key in firebase is a link, you can open a sub-node in a new tab and then edit that sub-node and its children.
Right click on a sub-node you want to edit or delete
Select open link in a new tab
Edit the sub-node in the new tab
1) Click on the Node you want to mass delete
2) Import an empty .json file (just containing curly braces, {} )
3) The node value will be set to null, in other words it is deleted or rather overridden with an empty node!
What you can do is to have an OnClickListener and call the remove value method to your DatabaseReference, like this:
mCart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDatabaseReference.removeValue();
}
});
I have the same problem... I'm a bit surprised because I though Firebase could easily scale to support huge amount of data (example million users, etc.).
I have a node with 80000 sub-nodes (each object has his own push-id) and I cannot delete or perform any action on it because the real-time doesn't work in Firebase console.
I think the only way to udate or delete the data it's to do it via JAVA code :(
Multiple times trying to load the specific keys can be tiresome. There is a python library that could do this for you easily.
http://ozgur.github.io/python-firebase/
I needed to delete a lot of keys and this helped me do that in one go.
What I do is export the entire tree, edit/add the node I want using an editor, then import the JSON and overwrite the previous node/tree. Problem solved! Risky though 😁

Drupal user permissions & odd content types

I have a permissions problem in Drupal. I want users to be able to create a certain node type, but there are two different paths I need to give them permissions for to let them do this. The type is content created by a module called isbn2node, and there are two ways to make content through it, each with different paths:
?=node/add/isbn2node-book
?=node/add/isbn2node_book/isbn2node
One has an underscore and the other one has a hyphen. The first path leads to a form that lets users enter information on a book manually; the second path lets them enter an ISBN, searches for it, and populates the form for them based on the results.
I've changed permissions in the People menu so they can add isbn2node-book content manually using the first path, but there isn't an option to let them use the second method. Aliasing the url so it didn't have node/add in the path didn't work either.
Creating a duplicate content type seems like an ugly solution to this; is there a more elegant way to let users access that second path?
A little code in a custom module using hook_node_access should do it.
$node is either a node object or the machine name of the content type on which to perform the access check (if the node is being created then the $node object is not available so it will be a string instead).
So this should do it:
function MY_MODULE_node_access($node, $op, $account) {
if ($op == 'create') {
$type = $node;
if($type == 'book' && $account->uid) return NODE_ACCESS_ALLOW;
}
}
I figured this out, and the issues I was having were specific to this content type. The ISBN2Node module requires users to have the Administer Nodes permission to use its lookup and bulk import features.
There is some extra code for the module's hook_permission and hook_menu sections submitted as a fix in the module's issues thread.

Take data from a field from exsisting node and make that the default value of a field in different content type

I don't know if I'm on the right track but I'm trying to let users of my web site create there own versions of pages on my web site.
Basically I'd like to make our documentation used as a starting point where they just add details and make a new page for themselves in the process.
I have a 'book' content type that I have changed with CCK and a 'client edits' content type that uses a nodereferencefromURL widget to link itself to the book node.
So simple version of what I'm saying is I have a link on my book pages that creates a node using client edits content type. I would like to put some fields on the client edits content type that take the values of some of the fields from the book page it is linked from.
I'm sure I'm missing something as I would have thought someone would have tried this before but I can't even find a hint on how to go about this.
All I really need is a point in the right direction if my current thinking is wrong.
Current thinking is that I use a php script to get the default value for a field on the new node add screen that drags the value for a field from the book I'm linking from.
I'm thinking this is the case because there is an option for default values for the field in cck manage fields that lets you put in a php value to return a default value for your field.
Am I on the right track or is there already a module or process that does what I'm talking about and I'm just too dumb to find it.
This sounds a little strange, are your client edits going to be a diff from the original node or just coppied data?
I would prehaps do it a more simple way, just have book nodes, and have different fields disaply depending on who edits it (enable the content_permissions module). That way you can use the node clone module to create the users copy.
You will need to make a module to contain your custom php code.
I ended up using rules to save information from the user and the cloned node into hidden fields.
One that saved the original node ID into a field when ever you create content of that type unless the url ends with Clone. This means that when you create the clone the original node ID is kept in the field.
That made it easy to use a views argument that took the node ID to make the clone appear along side the original when a user visits the original page.
The second rule trick was to compute a field that saved the "store name" from the profile of the user only when saving clone content.
This meant that there was a hidden field on the clone that stored the info so I could then use another views argument to restrict the view to only people with the same store name in their profile.
I am no good with PHP but I managed to find a snippet (can't remember where) that returns the store name of the current logged in user as the argument.
global $user;
profile_load_profile($user);
return $user->profile_store_name;

Drupal using views with CCK custom fields

I've got a Drupal site which uses a custom field for a certain type of node (person_id) which corresponds to a particular user. I want to create a view so that when logged in, a user can see a list of nodes 'tagged' with their person_id. I've got the view working fine, with a url of my-library/username but replacing username with a different username shows a list of all nodes tagged with that user. What I want to do is stop users changing the URL and seeing other users' tagged nodes. How can I do this? Is there somewhere where I can dictate that the only valid argument for this page is the one that corresponds with the current logged in user's username?
person_id = uid?
In this case, add argument with user:uid, then in Validation options select PHP Code, read comment of this field carefully:
Enter PHP code that returns TRUE or
FALSE. No return is the same as FALSE,
so be SURE to return something if you
do not want to declare the argument
invalid. Do not use . The
argument to validate will be
"$argument" and the view will be
"$view". You may change the argument
by setting "$handler->argument".
Add this code:
global $user;
$account = user_load('name'=>arg(1));
$handler->argument = $user->uid;
return $account->uid == $user->uid;
I'm not sure how you have setup your view, which gives some different options to solve this. A way that should work would be to set the default argument be the logged users id/username and remove the argument from the url.
Alternatively you could create your own filter which requires some work with the views API, but gives more control.

Resources