Order data by child node's value - Firebase - android

I'm trying to retrieve all recipes favorited by a user using this code, but no data is retrived
recipesQuery = mDatabase.child("recipes").orderByChild("favoritedBy").equalTo(getId());
This is my Structure:
{
"-KNnrgEmF8qCpsWiIMW4" : {
"favoriteCount" : 4,
"favoritedBy" : {
"0ZtxMXZ8iDV4u0POxu8n6cIwCX33" : true
},
"name" : "Recipe 1",
"recycleCount" : 0,
},
"-KNvq6Ts8RYxc0-O3B2t" : {
"favoriteCount" : 2,
"favoritedBy" : {
"0ZtxMXZ8iDV4u0POxu8n6cIwCX33" : true
},
"name" : "Recipe 2",
"recycleCount" : 0,
}
}
If I remove the .equalTo() method all data is retrieved, but thats not what I want.
What am I doing wrong?

There's currently no method to filter a query based on other objects than String, Boolean, or Double.
What I suggest is to restructure your database to something like this
{
"users": {
"userId1" : {
"name" : "User1",
"favorites": {
"-KNnrgEmF8qCpsWiIMW4" : true,
"-KNvq6Ts8RYxc0-O3B2t" : true
}
},
"userId2" : {
"name" : "User2",
"favorites": {
"-KNvq6Ts8RYxc0-O3B2t" : true
}
}
},
"recipes": {
"-KNnrgEmF8qCpsWiIMW4" : {
"favoriteCount" : 4,
"name" : "Recipe 1",
"recycleCount" : 0,
},
"-KNvq6Ts8RYxc0-O3B2t" : {
"favoriteCount" : 2,
"name" : "Recipe 2",
"recycleCount" : 0,
}
}
}
Then it's easier to get the recipes favorited by specific user.
mDatabase.child("users").child(userid).child("favorites")

Related

OrderByChild() results is depending on case of the words

Current firebase database is:
{
"user_type" : {
"number1" : {
"name" : "Puneet",
},
"number2" : {
"name" : "AMAN SINGH",
},
"number3" : {
"name" : "harsha",
},
"number4" : {
"name" : "abhishek",
},
"number5" : {
"name" : "Satya",
},
}
}
I want to sort the list by name in ascending order. So for this code is :
myRef.child("user_type").orderByChild("name");
But it is returning the result as:
{
"admin" : {
"number2" : {
"name" : "AMAN SINGH",
},
"number1" : {
"name" : "Puneet",
},
"number5" : {
"name" : "Satya",
},
"number4" : {
"name" : "abhishek",
},
"number3" : {
"name" : "harsha",
}
}
}
But I am expecting the following order:
{
"admin" : {
"number2" : {
"name" : "AMAN SINGH",
},
"number4" : {
"name" : "abhishek",
},
"number3" : {
"name" : "harsha",
}
"number1" : {
"name" : "Puneet",
},
"number5" : {
"name" : "Satya",
}
}
}
So instead of the current order, it is sorting first capital case letter words and then it is sorting small letter words and merging the list.
The order you're seeing is exactly what I would expect. This is because of the way strings naturally sort. UTF-8 strings with ascii data sort according to the ascii byte value of each character. As you can see from this table, all capital letters sort before all lowercase values. This explains the sort order you're seeing.
If you want the sort order to be alphabetical without regard to case, you will need to store a version of the name string with case normalized. It's common to store strings to sort like this in all lowercase. For example, instead of "AMAN SINGH", you would store "aman singh" in a special child used only for sorting.

mongodb Filtering of content state associated with objectid in array

I want to import the data through the filtering function.
I think we should probably use 'aggregate' instead of 'find'.
The conditions for the data I want are:
There is A Collection and B Collection.
The 'contents' of A Collection points to the "_id" of B Collection.
The corresponding value is only fetched when the "Visibility" value of the B Collection is "true".
"A" Collection:
{
"_id" : ObjectId("aaaaa"),
"title" : "study list",
"contents" : [ ObjectId("11111"), ObjectId("22222") ]
}
{
"_id" : ObjectId("bbbbb"),
"title" : "study list",
"contents" : [ ObjectId("33333"), ObjectId("44444") ]
}
{
"_id" : ObjectId("ccccc"),
"title" : "study list",
"contents" : [ ObjectId("55555") ]
}
"B" Collection:
{
"_id" : ObjectId("11111"),
"visibility" : true
}
{
"_id" : ObjectId("22222"),
"visibility" : true
}
{
"_id" : ObjectId("33333"),
"visibility" : true
}
{
"_id" : ObjectId("44444"),
"visibility" : false
}
{
"_id" : ObjectId("55555"),
"visibility" : false
}
== Data Result
{
"_id" : ObjectId("aaaaa"),
"title" : "study list",
"contents" : [ ObjectId("11111"), ObjectId("22222") ]
}
How can I get the data I want?
You can use below aggregation
db.collectionA.aggregate([
{ "$lookup": {
"from": "collectionB",
"localField": "contents",
"foreignField": "_id",
"as": "data"
}},
{ "$match": {
"data": {
"$not": {
"$elemMatch": { "visibility": false }
}
}
}}
])

Firebase security rules issue

I'm trying to restrict access to a particular groups if the user is not in the members list.
So this is my rule,
{
"rules": {
".read":"auth != null",
"groups": {
"$groupid":{
".read" : true,
".write" : "root.child('groupmembers').child($groupid).child('admins').child(root.child('users').child(auth.uid).child('username').val()).val()==true"
}
},
"groupchat":{
"$chatid":{
".read" : "root.child('groupmembers').child($chatid).child('members').child(root.child('users').child(auth.uid).child('username').val()).val()==true",
".write" : "root.child('groupmembers').child($chatid).child('members').child(root.child('users').child(auth.uid).child('username').val()).val()==true"
}
}
}
}
The first rule for "groups">"$groupid" works perfectly. But I'm getting problem with second rule for "groupchat"
DataStructure ex:
Group Chat structure
"groupchat" : {
"testinggroup" : {
"chat" : {
"-KiYN6RKZOyWI-qufWn3" : {
"message" : "Hey",
"timestamp" : 1493094660399,
"type" : "text",
"username" : "user2"
}
},
"lasttimestamp" : 1493094660674
}
}
Users Structure
"users":{
"ujciTL9oFKNylcgiGcdYqUxjcgA3" : {
"email" : "example#gmail.com",
"username" : "user1"
}
}
groupmembers structure
"groupmembers":{
"groupid":{
{
"admins" : {
"user1" : true,
"user3" : true
},
"members" : {
"user1" : true,
"user2" : true,
"user3" : true,
"user4" : true
}
}
}
}
groups structure
"groupid"{
{
"category" : "group category",
"creator" : "creator uid",
"desc" : "group desc",
"id" : "groupid",
"image" : "url",
"name" : "groupname"
}
}
Operation ex:
FirebaseDatabase.getInstance()
.getReference()
.child("groupchat")
.child(j)
.child("lasttimestamp")
.setValue(ServerValue.TIMESTAMP);
So to debug the errors
I added "myusername" in place of root.child('users').child(auth.uid).child('username').val()
and it's working.
But in the previous rule("For groups child") I added the same thing and it was working.
I don't know why I'm getting error.

Android Firebase, server side filtering for Recyclerview

Following is my firebase data structure
{
"ticketing" : {
"1476639649079-mahto" : {
"agentId" : 0,
"agent_status" : "1_Dispatched",
"approverId" : 0,
"contractorId" : 0,
"dateTime" : "16-10-2016 13:40 PM",
"priority" : "MEDIUM",
"requester" : {
"issue" : "issue 3",
"location" : "location 3",
"priority" : "Medium",
"shop" : "shop 3",
"site" : "site 3",
"userInfo" : {
"email" : "m#gmail.com",
"firstname" : "mahto",
"isLoggedin" : true,
"lastname" : "pancha",
"loggedin" : true,
"number" : "123123123",
"password" : "q",
"role" : "fieldagent",
"userid" : "2",
"username" : "q"
}
},
"requesterId" : 2,
"status" : "Incoming",
"ticketNumber" : "1476639649079-mahto"
},
"1476741838857-mahto" : {
"agentId" : 1,
"agent_status" : "1_Incoming",
"approverId" : 0,
"contractorId" : 0,
"dateTime" : "17-10-2016 18:03 PM",
"priority" : "HIGH",
"requester" : {
"issue" : "Description 3",
"location" : "Location 3",
"priority" : "HIGH",
"shop" : "shop 3",
"site" : "site 3",
"userInfo" : {
"email" : "m#gmail.com",
"firstname" : "mahto",
"isLoggedin" : true,
"lastname" : "pancha",
"loggedin" : true,
"number" : "123123123",
"password" : "q",
"role" : "fieldagent",
"userid" : "2",
"username" : "q"
}
},
"requesterId" : 2,
"status" : "Incoming",
"ticketNumber" : "1476741838857-mahto"
}
}
}
Database refrence
mDatabase = FirebaseDatabase.getInstance().getReference().child("ticketing");
mDatabase.orderByChild("agent_status").equalTo("1_Incoming");
and attached to recyclerview adapter
mAdapter = new FirebaseRecyclerAdapter<Ticket, AgentTicketHolder>(Ticket.class, R.layout.agent_ticket_cardview, AgentTicketHolder.class, mDatabase) { .. }
My expected result is that i will get only one node i.e 1476741838857-mahto which has agent_status value equal to 1_Incoming.
But i'am getting both the nodes in my recylerview.
When you call filtering methods, the Firebase SDK returns a new object for the resulting query. So you need to capture the reference to that object and pass that into the adapter:
mDatabase = FirebaseDatabase.getInstance().getReference().child("ticketing");
Query query = mDatabase.orderByChild("agent_status").equalTo("1_Incoming");
mAdapter = new FirebaseRecyclerAdapter<Ticket, AgentTicketHolder>
(Ticket.class, R.layout.agent_ticket_cardview, AgentTicketHolder.class, query) { .. }

How to display data that depends on other entity?

Having the following data:
"animals" : {
"a1" : {
"name" : "Dog"
},
"a2" : {
"name" : "Cat"
},
"a3" : {
"name" : "Cow"
}
},
"users" : {
"u1" : {
"favAnimals" : {
"a1" : true,
"a2" : true
},
"name" : "Danilo"
}
}
How can I display for the user, using the FirebaseListAdapter, the complete list of animals, highlighing user's favorite animals?
Is it possible to query and join them, to get a Database Reference that would watch for changes both in "/animals" and "/users/$uid/favAnimals" and return something like:
"animals" : {
"a1" : {
"name" : "Dog",
"fav" : true
},
"a2" : {
"name" : "Cat"
"fav" : true
},
"a3" : {
"name" : "Cow"
}
}

Categories

Resources