Query a RealmList<Integer> with a parameter - android

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();

Related

limitToLast is being ignored

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) {...}

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.

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)

RealmObject with #PrimaryKey only

I have API that returns a list of objects. These objects have relations to another objects. But API returns only IDs for them. In order to get full object I have to use another API. For instance:
class Owner extends RealmObject {
...
RealmList<Cat> cats;
}
class Cat extends RealmObject {
#PrimaryKey
String id;
String name;
}
so when I receive list of Owners I store them in database like this:
for (OwnerDto o : owners) {
Owner owner = new Owner();
...
RealmList<Cat> catsList = new RealmList<>();
for (Cat c : o.cats) {
Cat cat = new Cat();
cat.setId(c.id);
catsList.add(cat);
}
owner.setCats(catsList);
realm.copyToRealmOrUpdate(owner);
}
but in this case all the cats' names are deleted if they were populated before.
Is it possible to create RealmObject with ID only in order to set relation, and fill it with date afterwords ? Or specify relation with Id only ? Or any other solution ?
UPDATE:
I came up with solution like this:
for (OwnerDto o : owners) {
Owner owner = new Owner();
...
RealmList<Cat> catsList = new RealmList<>();
for (Cat c : o.cats) {
Cat cat = realm.where(Cat.class)
.equalsTo("id", c.id)
.findFirst();
if (cat == null) {
cat = new Cat();
}
cat.setId(c.id);
catsList.add(cat);
}
owner.setCats(catsList);
realm.copyToRealmOrUpdate(owner);
}
Here I figured out that there is method realm.objectForPrimaryKey(User.self, key: "key") for swift but I did not fund analog in java version.
It would be nice to have in this situation something like realm.getOrCreate(Cat.class, c.id) method. Is there any ?
It's pretty rough to do that if you don't have the whole objects before you want to link them together, because you can't just store a RealmList<T> of primitives, only RealmList<T extends RealmObject>.
So your options are:
1.) have the cats in your Realm and then download the Owner into which you piece it together with realm queries.
realm.beginTransaction();
Owner owner = new Owner();
owner.setCats(new RealmList<Cat>());
for(int i = 0; i < listOfCats.size(); i++) {
String id = listOfCats.get(i);
Cat cat = realm.where(Cat.class).equalTo("id", id).findFirst();
owner.getCats().add(cat);
}
realm.commitTransaction();
2.) have a RealmList<RealmString> in which you store the IDs.
public class RealmString extends RealmObject {
private String value;
public String getValue() { return value; }
public void getValue(String value) { this.value = value; }
}
You'll probably need to use some ugly queries afterwards.
RealmResults<Owner> ownerOfCat = realm.where(Owner.class)
.equalTo("catIds.value", catId).findAll();

OrmLite execute sql statement

I have a database in OrmLite.
Here one of the tables — Field:
#DatabaseTable
public class Field {
#DatabaseField(generatedId = true)
private long id;
#DatabaseField
private String type;
#ForeignCollectionField(eager = true)
private Collection<FieldListValue> listValue;
...
}
I want to delete some values from the table like in this way:
List<Field> fields = fieldDao.queryForAll();
for (Field field : fields) {
if (field.getType().equals("list") && field.getListValue().size() == 0) {
fieldDao.delete(field);
}
}
But how can I execute this query with DeleteBuilder ?
The problem with this piece of code ...(SELECT COUNT(listValue) FROM Field) = 0
But how can I execute this query with DeleteBuilder ?
There is not a direct way that you can use the DeleteBuilder to do this because the foreign objects actually have no information in the Field class.
However, here's one way you can accomplish this using a raw-query and then the DeleteBuilder.
In approximate code:
qb = fieldListValueDao.queryBuilder();
// raw query for the field_ids in the fieldListValue table
rawResults = qb.queryRaw("SELECT field_id FROM fieldListValue GROUP BY field_id",
new RawRowMapper<Integer>() {
// each result row is a single integer in the 0th column
public Integer mapRow(String[] columnNames, String[] resultColumns) {
return Integer.parseInt(resultColumns[0]);
}
});
For help on the raw queries see: http://ormlite.com/docs/raw-queries
Once you have the raw-results of the field_id values, you can then do:
deleteBuilder = fieldDao.deleteBuilder();
// delete any rows that are not in the raw-results -- who have no fieldListValue entries
deleteBuilder.where().notIn("id", rawResults);
deleteBuilder.delete();
You also might be able to do it with the notIn("id", queryBuilder) method:
qb = fieldListValueDao.queryBuilder();
qb.selectColumns("field_id");
qb.groupBy("field_id");
...
deleteBuilder = fieldDao.deleteBuilder();
deleteBuilder.where().notIn("id", qb);
deleteBuilder.delete();
I would need to check this to make sure however.
Hope this helps.
You can do it this way
//get instance of DeleteBuilder
DeleteBuilder<Field, Integer> deleteBuilder = fieldDao.deleteBuilder();
//construct yours WHERE
//in this exampe we select fields with "id"=0
deleteBuilder.where().eq("id", 0);
//call delete
deleteBuilder.delete();
If you want to delete rows, that you want after yours codes conditions you can form an ArrayList of objects to delete and then pass their ids to deleteBuilder where statement like so
List<Integer> ids= new ArrayList<Integer>();
List<Field> fields = fieldDao.queryForAll();
List<Field> fieldsToDelete = new ArrayList<Field>();
for (Field field : fields)
{
if (field.getType().equals("list") && field.getListValue().size() == 0)
{
ids.add(field.getId);
fieldsToDelete.add(field);
}
}
fieldDao.delete(ids);
//or
fieldDao.delete(fieldsToDelete);
//or
//get instance of DeleteBuilder
DeleteBuilder<Field, Integer> deleteBuilder = fieldDao.deleteBuilder();
//construct yours WHERE
//in this exampe we select fields with "id"=0
deleteBuilder.where().in("id", ids);
//call delete
deleteBuilder.delete();

Categories

Resources