In realm, how to query from a RealmList (Android) - android

Check out following classes:
class Person{
int id;
String name;
RealmList<Mail> mails;
...
}
class Mail{
int id;
String content;
...
}
I have a Person object (ie: mPerson) and I am accessing all Mails of the Person object by mPerson.getMails(). Till here everything is cool.
Here is the question: Is there way to query over the returned list such as findAllSortedAsync()?

Just use RealmList.where() to create a query. You can find document here
For example:
RealmList<Mail> mails = person.getMails();
RealmResults<Mail> results = mails.where().equalTo("id", 1).findAllSortedAsync();

RealmResults<Contact> contacts = mRealm.where(Contact.class).findAll();
int size = contacts.size();
for (int i = 0;i<size;i++){
Contact contact = contacts.get(i);
RealmList<EMail> eMails = contact.emails;
}

Related

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

Realm query with List

I'm using realm to store my data on Android. Awesome framework! Now the only problem I'm now having is:
I got a array list strings with id's of Countries in my database.
Now I retrieve my Drinks that contains a relationship to countries.
Is there a way that I could to do a query like this:
String [] ids;
realm.where(Drinks.class).equalsTo("country.id", ids);
Something like that?
Or do I really need to do a query to get me all drinks and then filter the list manually?
EDIT:
My classes:
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private Country country;
}
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
}
What you want to do is possible with link queries in theory (searching for "country.id"), however link queries are slow. Also you'd need to concatenate a bunch of or() predicates together, and I would not risk that with a link query.
I would recommend using the following
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private Country country;
#Index
private String countryId;
}
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
}
And when you set the Country in your class, you also set the countryId as country.getId().
Once you do that, you can construct such:
RealmQuery<Drinks> drinkQuery = realm.where(Drinks.class);
int i = 0;
for(String id : ids) {
if(i != 0) {
drinkQuery = drinkQuery.or();
}
drinkQuery = drinkQuery.equalTo("countryId", id);
i++;
}
return drinkQuery.findAll();
Since the Realm database has added RealmQuery.in() with the version 1.2.0
I suggest using something like this.
//Drinks
public class Drinks extends RealmObject {
#PrimaryKey
private String id;
private String name;
private String countryId;
//getter and setter methods
}
//Country
public class Country extends RealmObject {
#PrimaryKey
private String id;
private String name;
//getter and setter methods
}
The code to use inside activity/fragments to retrieve drink list
String[] countryIdArray = new String[] {"1","2","3"} //your string array
RealmQuery<Drinks> realmQuery = realm.where(Drinks.class)
.in("countryId",countryIdArray);
RealmResults<Drinks> drinkList = realmQuery.findAll();
In latest version of Realm 7+, you can use anyOf to match a field against a list of values.
anyOf("name", new String[]{"Jill", "William", "Trillian"})
in older versions, use in instead of anyOf and with kotlin use oneOf instead of in.
see this issue
To match a field against a list of values, use in. For example, to find the names “Jill,” “William,” or “Trillian”, you can use in("name", new String[]{"Jill", "William", "Trillian"}). The in predicate is applicable to strings, binary data, and numeric fields (including dates).
Doc.-> https://realm.io/docs/java/latest#queries

Realm.io - Is it possible to find object by its subobject?

Doctor includes object Organization sub object:
#PrimaryKey
private int doctorId;
private FullName fullName;
private Age age;
private Organization organization;
private Position position;
private String category;
private String loyalty;
private List<Specialization> specializations;
private Contacts contacts;
Organization model has following parameters:
#PrimaryKey
private OrganizationId organizationId;
private String organizationName;
private String key;
// private Address address;
private String address;
private String phoneNumber;
Filling values like this:
Organization organization = realm.createObject(Organization.class); // Create a new object
OrganizationId organizationId = realm.createObject(OrganizationId.class);
organizationId.setAggregateId("1");
organization.setOrganizationId(organizationId);
organization.setOrganizationName("1-я Клиника Ташкентской Медицинской Академии");
organization.setAddress("Адрес: г. Ташкент, ул. Фароби, 2");
organization.setPhoneNumber("Тел.: (+99871) 214-51-01, 214-50-86, 214-50-43");
organization.setKey(organization.getOrganizationName().toLowerCase());
Doctor doctor = realm.createObject(Doctor.class);
//FULL NAME
FullName fullName = realm.createObject(FullName.class);
fullName.setFirstName("Joe");
fullName.setLastName("Richard");
fullName.setMiddleName("Brown");
doctor.setFullName(fullName);
//CONTACTS
Contacts contacts = realm.createObject(Contacts.class);
String[] phoneNumbers = {"+998903735173"};
contacts.setPhoneNumbers(phoneNumbers);
doctor.setContacts(contacts);
//ORGANIZATION
doctor.setOrganization(organization);
For example, this code returns all doctors with A category:
RealmQuery<Doctor> query = realm.where(Doctor.class);
RealmResults<Doctor> rDoctors = query.contains("category", "A").findAll();
return rDoctors;
My app logic like this: first of all, I open list of organizations. When User clicks on one organization. This will open list of doctors.
So my question is can I find doctors by its sub object(Organization)? Something like this
RealmQuery<Doctor> query = realm.where(Doctor.class);
RealmResults<Doctor> rDoctors = query.someMagicalMethod("organization", organization1).findAll();
return rDoctors;
PS. Yes, I can get it by going deep into organization. I was wondering does Realm.io makes search by object possible. Anyways I love Realm.io
I think it i possible. You can check it out here: http://realm.io/docs/java/latest/#link-queries
As per your case, you can try my following code:
RealmResults<Doctor> rDoctors = realm.where(Doctor.class)
.equalsTo("organization.organizationId", organizationId)
.findAll();
return rDoctors;
Please let me know if it works for you.

Trying write a query with ORMLite?

I'm trying write a query using ORMLite. I need this query check a id of customer in other entity. How could I do it ?
Entities
#DatabaseTable(tableName = "customer")
public class Customer {
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private String name;
#DatabaseField
private Sale sale;
//gets sets
}
#DatabaseTable(tableName = "sale")
public class Sale{
#DatabaseField(generatedId = true)
private Integer id;
#DatabaseField
private Customer customer;
#DatabaseField
private Integer status;
//gets sets
}
Query
Customer customer = new Customer();
customer.setId(1);
customer.setName("Fernando Paiva");
QueryBuilder<Sale, Integer> qb = saleDAO.queryBuilder();
Where where = qb.where();
where.eq("sale.customer.id", customer.getId());
where.and();
where.eq("sale.status", 1);
PreparedQuery<Sale> pq = qb.prepare();
List<Sale> list = saleDAO.query(pq);
Log.i("SALE LIST->", list.size() + "");
You need to use JOIN
Here your example using Join:
First of all, you need a QueryBuilder to each Dao.
You can apply your filter to each QueryBuilder separately
Last but not least, you join the main QueryBuilder (Sales) with the Customer's QueryBuilder and
perform the query.
Here the code
Dao<Sale, Integer> saleDao = DaoManager.createDao(getConnectionSource(), Sale.class);
Dao<Customer, Integer> customerDao = DaoManager.createDao(getConnectionSource(), Customer.class);
QueryBuilder<Sale, Integer> saleQa= saleDao.queryBuilder();
saleQa.where().eq("status", 1);
QueryBuilder<Customer, Integer> customerQa = customerDao.queryBuilder();
customerQa.where().idEq(customer.getId());
sales = saleQa.join(customerQa).query();
Are you trying to use OrmLite to check if the customer id is the same as the sale id and get all of the matching result? If so the below code will do that
qb.where().eq("id", customer.id);
List<Sale> results = saleDAO.query(qb.prepare());
Update:
After rereading your question I realized what you're trying to do
qb.where().in(Sale.customer, id);
See this question for further details.
Ormlite Foreign Entity Searching

ORMLite where clausule in String Array

I use ormlite and I have a db with a field:
public static final String NAME = "name";
#DatabaseField (canBeNull = false, dataType = DataType.SERIALIZABLE, columnName = NAME)
private String[] name = new String[2];
And I would like to get all elements that name[0] and name[1] are "car". I try to add a where clausule like:
NAMEDB nameDB = null;
Dao<NAMEDB, Integer> daoName = this.getHelper().getDao(NAMEDB.class);
QueryBuilder<NAMEDB, Integer> queryName = daoName.queryBuilder();
Where<NAMEDB, Integer> where = queryName.where();
where.in(nameDb.NAME, "car");
But it doesn't work because it's an array string.
I have other fields:
public static final String MARK = "mark";
#DatabaseField (canBeNull = false, foreign = true, index = true, columnName = MARK)
private String mark = null;
And I can do this:
whereArticulo.in(nameDB.MARK, "aaa");
How can I solve my problem? Thanks.
It seems to me that a third option to store a string array (String[] someStringArray[]) in the database using Ormlite would be to define a data persister class that converts the string array to a single delimited string upon storage into the database and back again to a string array after taking it out of the database.
E.g., persister class would convert ["John Doe", "Joe Smith"] to "John Doe | Joe Smith" for database storage (using whatever delimiter character makes sense for your data) and converts back the other way when taking the data out of the database.
Any thoughts on this approach versus using Serializable or a foreign collection? Anyone tried this?
I just wrote my first persister class and it was pretty easy. I haven't been able to identify through web search or StackOverflow search that anyone has tried this.
Thanks.
As ronbo4610 suggested, it is a good idea to use a custom data persister in this case, to store the array as a string in the database separated by some kind of delimiter. You can then search the string in your WHERE clause just as you would any other string. (For example, using the LIKE operator)
I have implemented such a data persister. In order to use it, you must add the following annotation above your String[] object in your persisted class:
#DatabaseField(persisterClass = ArrayPersister.class)
In addition, you must create a new class called "ArrayPersister" with the following code:
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.SqlType;
import com.j256.ormlite.field.types.StringType;
import org.apache.commons.lang3.StringUtils;
public class ArrayPersister extends StringType {
private static final String delimiter = ",";
private static final ArrayPersister singleTon = new ArrayPersister();
private ArrayPersister() {
super(SqlType.STRING, new Class<?>[]{ String[].class });
}
public static ArrayPersister getSingleton() {
return singleTon;
}
#Override
public Object javaToSqlArg(FieldType fieldType, Object javaObject) {
String[] array = (String[]) javaObject;
if (array == null) {
return null;
}
else {
return StringUtils.join(array, delimiter);
}
}
#Override
public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
String string = (String)sqlArg;
if (string == null) {
return null;
}
else {
return string.split(delimiter);
}
}
}
Unfortunately ORMLite does not support querying fields that are the type SERIALIZABLE. It is storing the array as a serialized byte[] so you cannot query against the values with an IN query like:
where.in(nameDb.NAME, "car");
ORMLite does support foreign collections but you have to set it up yourself with another class holding the names. See the documentation with sample code:
http://ormlite.com/docs/foreign-collection

Categories

Resources