limitToLast is being ignored - android

I need some help please. I'm trying to retrieve the last 2 values from the firebase database, but the following code returns all 3 values. What am I doing wrong?
FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference mDatabaseReference = mFirebaseDatabase.getReference().child("data/" + userId + "/contents/");
mDatabaseReference.limitToLast(2);
mFirebaseAdapter = new FirebaseRecyclerAdapter<MyObject, MyObjectViewHolder>(
MyObject.class,
R.layout.item,
MyViewHolder.class,
mDatabaseReference) {...}
This is how my database structure looks like:
d5TPjSY2rJRrFJUF7nPrQWcGAjh1
contents
-KqKbcnMfHwYKChXHiCA
-KqKbibX3f96ceVfoTLV
-KrBrtsHeLaWv_gEUjIT
where d5TPjSY2rJRrFJUF7nPrQWcGAjh1 is the userId.
Thanks in advance!

When you call limitToLast() (or any other of the query methods), it returns a new object. You must use this new object.
DatabaseReference mDatabaseReference = mFirebaseDatabase.getReference().child("data/" + userId + "/contents/");
Query query = mDatabaseReference.limitToLast(2);
mFirebaseAdapter = new FirebaseRecyclerAdapter<MyObject, MyObjectViewHolder>(
MyObject.class,
R.layout.item,
MyViewHolder.class,
query) {...}

Related

Query a RealmList<Integer> with a parameter

My model is a Category, which has a list of parent id's.
private RealmList<Integer> parentCategories = new RealmList<>();
I need the subcategories from a given category.
My Query looked like this:
Integer[] intArray = new Integer[1];
intArray[0] = category.getId();
Realm realm = Realm.getDefaultInstance();
return realm.where(Category.class)
.contains("parentCategories", category.getParentCategories())
.findAll();
And I also tried this:
Realm realm = Realm.getDefaultInstance();
RealmQuery<Category> query = realm.where(Category.class);
for (Integer id : category.getParentCategories()) {
query.or().equalTo("id", id);
}
RealmResults<Category> results = query.findAll();
But both didn't work.
Could you point me in the right direction?
UPDATE: What I'm trying to do is not supported in a RealmQuery yet.
Thanks for pointing this out guys!
if you want to query object list variables you need to use "in" -
String[] parentCategoriesArray = new String[]{"example"};
Realm realm = Realm.getDefaultInstance();
return realm.where(Category.class)
.in("parentCategories", parentCategoriesArray)
.findAll();

Firebase setValue not creating unique child node?

ArrayList<ListingModel> list = new ArrayList<ListingModel>();
list.add(model);
list.add(model2);
list.add(model3);
list.add(model4);
for (ListingModel m : list) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("node");
myRef.push().setValue(m);
}
I am trying to save 4 objects from android app to firebase database. So I am using loop to store data into the node. It should have create 4 different child with auto id and stored the object there . But it's only storing the last model in one unique id like image below :
How can I save all four objects(data in list) with unique id each?
Fully documented at firebase
private void writeNewPost(String userId, String username, String title, String body) {
// Create new post at /user-posts/$userid/$postid and at
// /posts/$postid simultaneously
String key = mDatabase.child("posts").push().getKey();
Post post = new Post(userId, username, title, body);
Map<String, Object> postValues = post.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/posts/" + key, postValues);
childUpdates.put("/user-posts/" + userId + "/" + key, postValues);
mDatabase.updateChildren(childUpdates);
}
Put your models in a map, put them, and use updateChildren
The best way to do is to use for loop.
ArrayList<ListingModel> list = new ArrayList<ListingModel>();
list.add(model);
list.add(model2);
list.add(model3);
list.add(model4);
for (int i =0; i<list.size();i++){
ListingModel model = list.get(i);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("node");
myRef.child(i).setValue(model);
}
So the problem was with how I set the model (Sorry for partial code in my question)
ListingModel model = new ListingModel();
model.setTitle("test0");
ListingModel model1 = new ListingModel();
model.setTitle("test1");
ListingModel model2 = new ListingModel();
model.setTitle("test2");
ListingModel model3 = new ListingModel();
model.setTitle("test3");
I was instantiating different models, but only altering value of first model.
model1, model2, and model3 was empty hence was not appearing in firebase database for being an empty object.
I think the code only read push once. And when you using the same id to write the data, you will overwrite the previous version.
ArrayList<ListingModel> list = new ArrayList<ListingModel>();
list.add(model);
list.add(model2);
list.add(model3);
list.add(model4);
for (ListingModel m : list) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("node");
String modelID = myRef.push().getKey();
myRef.child(modelID).setValue(m);
}
Try this, I hope it helps.
Btw, practice using updateChildren rather than setValue for saving your data.

Reading from a simple FireBase Database

I'm having some issues reading from a Firebase Database.
I have a pretty simple layout
{
"lot" : {
"lot1" : "low",
"lot2" : "low",
"lot3" : "low"
}
}
Of course MyAppName { } is above this all.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getInstance().getReference();
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
lotMap = (HashMap) dataSnapshot.getValue();
Log.d("[Directions Activity]: ", "Lot1 value ====== " +lotMap.get("lot"));
Iterator it = lotMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
Log.d("[Directions Activity]: ", "iterator " + pair.getKey() + " = " + pair.getValue());
System.out.println();
it.remove(); // avoids a ConcurrentModificationException
}
}
Here's what returns from log
D/[Directions Activity]:: Lot1 value ====== null //null obviously
//because key lot1 doesn't exist
D/[Directions Activity]:: lot = {lot3=low, lot2=low, lot1=low}
So to me, it looks like it's returning the string {lot3=low, lot2=low, lot1=low}, but I'd like to be able to get an array, with each value if possible.
Is this achievable??
I had the same question and this is what i used. Modifying to fit the question here
private List<String> lotList;
lotList = new ArrayList<>();
DatabaseReference reference= database.getInstance().getReference().child("lot");
Now adding value event listener
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> mData = dataSnapshot.getChildren();
for(DataSnapshot d : mData){
String lot_string = d.getValue(String.class);
lotList.add(lot_string);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
There's some tweak in your code. Your
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getInstance().getReference();
should be write like this,
DatabaseReference myRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference database = myRef.child("anyValueNameYouSpecifyInConsole");
Those 2 lines should be declare outside onCreate method. The one that you need to specify with addValueEventListener is the 2nd DatabaseReference, not the first one. So, it should looks like this from my example,
database.addValueEventListener (new ValueEventListener)
and it will import method.
If you wish the data to be displayed in a particular TextView, then just findViewById the TextView you wanna use and include it in onDataChange method like so,
String x = dataSnapshot.getValue(String.class);
textViewNameDeclared.setText(x);
And don't forget to change the security rule for reading.
you can use typecast to JSONObject and parse the JSONObject
JSONObject jsonObject= new JSONObject((Map)dataSnapshot.getValue());
JSONObject jsonObj= (JSONObject) jsonObject.get("lot");
for (Object key : jsonObj.keySet()) {
//based on you key types
String keyStr = (String)key;
Object keyvalue = jsonObj.get(keyStr);
//Print key and value
System.out.println("key: "+ keyStr + " value: " + keyvalue);
}
if you using java 8 than you use lamada expression.

Converting SQLite query to Firebase database query

I developed this app for my senior project and used SQLite and stored everything locally. I want to convert everything to Firebase now but there aren't that many tutorials out there, at least for what I'm trying to do. My question is how would I go about converting a query like the below to a Firebase database query?
public ArrayList<String> getAllBeautyItems() {
itemsList.clear();
dbHelper.getReadableDatabase();
ArrayList<String> itemNames = new ArrayList<>();
String[] tableColumns = new String[]{
Constants.ITEM_NAME, Constants.CATEGORY
};
String whereClause = Constants.CATEGORY + "=?";
String[] whereArgs = new String[]{
"beauty"
};
Cursor result = db.query(Constants.ITEMS_TABLE_NAME, tableColumns, whereClause, whereArgs,
null, null, null, null);
if (result.moveToFirst()) {
do {
itemNames.add(result.getString(result.getColumnIndex(Constants.ITEM_NAME)));
} while (result.moveToNext());
}
result.close();
return itemNames;
}
and then in a fragment I'm calling a setName, so how do I get the result of that query and apply it like in the below?
private ArrayList<Items> refreshData() {
dbItems.clear();
final ArrayList<String> itemNames = adapter.getAllBeautyItems();
ArrayList<String> itemImages = adapter.getAllBeautyImages();
ArrayList<Integer> itemPrices = adapter.getAllBeautyPrices();
ArrayList<String> itemDescriptions = adapter.getAllBeautyDescriptions();
ArrayList<String> itemLocations = adapter.getAllBeautyLocations();
ArrayList<String> itemLats = adapter.getAllBeautyLats();
int totalItems = adapter.getTotalBeautyItems();
String formattedItems = Utils.formatNumber(totalItems);
totalItemsText.setText("Total Items: " + formattedItems);
ArrayList<Items> items = new ArrayList<>();
for (int i = 0; i < itemNames.size(); i++) {
Items item = new Items();
item.setItemName(itemNames.get(i));
item.setItemImage(itemImages.get(i));
item.setItemPrice(itemPrices.get(i));
item.setItemDescription(itemDescriptions.get(i));
item.setItemLocation(itemLocations.get(i));
item.setLatLocation(itemLats.get(i));
items.add(item);
}
return items;
}
First of all, I wanna recommend you this: https://firebase.googleblog.com/2013/10/queries-part-1-common-sql-queries.html
It's a tutorial that show you how yo make typical SQL queries in Firebase, BUT, like the owner says:
While this post still contains some useful and relevant information, we have released advanced query functionality which solves a lot of the problems this post discusses.
So, now, I will tell you the basic query that may solve your problem.
As I see, you have a table about Items, and you are doing a SELECT where that item's Category is beauty.
I will assume that you already know how data is stored in Firebase, so I'm not making us lose time explaining to you about the database tree.
Reading
You will need something like:
Query query = FirebaseDatabase.getInstance().getReference()
.child("items")
.orderByChild("Category")
.equalTo("beauty");
This, after attaching the listener to it, will search in the items tree, those items where the value of its category child, is beauty. The logic here is:
FirebaseDatabase.getInstance().getReference() -> Go to the main node
.child("items") -> Go to the Items node
.orderByChild("Category") -> Order them by its Category child
.equalTo("beauty") -> Look only at those with the "beauty" value
You will always need to do an orderBy*() to append an equalTo() and mimic the WHERE clause.
And, in your listener you will have something like:
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
List<Item> list = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Item item = snapshot.getValue(Item.class);
list.add(item);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//
}
};
query.addValueEventListener(eventListener);
And, since all Firebase connections are async, you will need a calback method to return the list after the for.
Writing
Now, for the upload, you will need a DatabaseReference, instead of a Query, like:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("items");
And all you need to do is:
ref.push().setValue(item); -> For a random ID
ref.child(key).setValue(item); -> For an specific ID (key)

How to add new data in firebase android

This is my logic for adding new person in firebase realtime databse. But instead of making a new entry it is just updating the old data with new one.
buttonSave.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
/*
new Firebase(Config.FIREBASE_URL)
.push()
.child("title")
.setValue(text.getText().toString());
*/
Firebase ref = new Firebase(Config.FIREBASE_URL);
String name = editTextName.getText().toString().trim();
String address = editTextAddress.getText().toString().trim();
//Creating Person object
Person person = new Person();
//Adding values
person.setName(name);
person.setAddress(address);
ref.child("Person").setValue(person);
}
});
new Firebase(Config.FIREBASE_URL).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
//Getting the data from snapshot
Person person = postSnapshot.getValue(Person.class);
//Adding it to a string
String string = "Name: "+person.getName()+"\nAddress: "+person.getAddress()+"\n\n";
//Displaying it on textview
textViewPersons.setText(string);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
What is wrong here? Can anyone help me on this?
You are using always the same ref
Person person = new Person();
//Adding values
person.setName(name);
person.setAddress(address);
ref.child("Person").setValue(person);
Check the doc:
Using setValue() in this way overwrites data at the specified location, including any child nodes.
In your case you are overriding the same data for this reason.
You should use the push() method to generate a unique ID every time a new child is added to the specified Firebase reference.
Person person = new Person();
//Adding values
person.setName(name);
person.setAddress(address);
DatabaseReference newRef = ref.child("Person").push();
newRef.setValue(person);
You can add a new Child to your data, such as:
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
String userId = user.getUid();
Firebase rootRef = new Firebase(Config.USER_URL);
Firebase userRef = rootRef.child("Users");
Person newUser = new Person();
newUser.setFirstName(firstName);
newUser.setLastName(lastName);
userRef.child(userId).setValue(newUser);
The userId varies when the logging user is different, therefore, you will always go to a new data list for a new logged-in-user in the userId under Users.
every time when you optate to insert data to database call the follwing method.
You can integrate as many attributes you optate.It will engender a unique key everytime and insert records.
public void insert2database(double latitude,double longitude,String name) {
HashMap<String,String> student=new HashMap<>();
student.put("Name",name);
student.put("Lat", String.valueOf(latitude));
student.put("Long", String.valueOf(longitude));
student.put("Phone", String.valueOf("78787500000"));
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference tasksRef = rootRef.child("USERS").push();
tasksRef.setValue(student);
}
It will be in the database hierarchy like this
-database-4df17-default-rtdb
-USERS
-MUqgUu8zUpYcIaUVSsj
-Lat: "25.9405145"
-Long: "79.9100086"
-Name:"Dilroop"
-Phone: "78787500000"
-MUqoL2AUQFjH2ggKWev
-Lat: "32.9405145"
-Long: "73.9178186"
-Name: "Sanghavi"
-Phone: "78787500000"
-MUsfc-H-7KdQhrkHb_F
-Lat: "52.9405145"
-Long: "79.9175856"
-Name: "MDNSRF"
-Phone: "78787500000"
You are referencing to the "Person" child and setting it's value (setValue()) every time you click buttonSave, which only edits that one child. Try to use push() instead.

Categories

Resources