Realm Query with 2 Columns and distinct - android

I would like to create a Realm Android query, but dont know how to do this.
My realm Object is the following.
public class test extends RealmObject {
#PrimaryKey
int id;
String test1;
String test2;
}
My query should search in test1 and test2. So if either test1 or test2 is equals to the filter String the RealmObject should be inserted into my list. It is possible that test1 and test2 both have the same value. If this is the case the Object should only appear once in my list and not twice.
My query which is not working:
List<test> games = db.where(test.class)
.contains("test1", charText,
Case.INSENSITIVE).distinct().where(test.class)
contains("test2", charText, Case.INSENSITIVE)
.distinct();
At last I want to sort the list after test1.

You could use RealmQuery::or to combine the conditions:
List<test> games = db.where(test.class)
.contains("test1", charText, Case.INSENSITIVE)
.or()
.contains("test2", charText, Case.INSENSITIVE)
.findAllSorted("test1");
You can find other examples of this type of query in the documentation
Even if the test1 and test2 contain the same value, the same record will not appear twice in the list so you do not need to add the distinct constraint on your query.

Related

Android Room: select list of custom objects removing duplicates by a specific property

I'm using Room library to retrive a List without duplicates for property "text".
This is the code of the query in MyObjectDao class:
#Query("SELECT DISTINCT * FROM historyentity WHERE text LIKE :inputText || '%'")
List<MyObject> findByText(String inputText);
I also post MyObject class:
#Entity
public class MyObject {
#PrimaryKey(autoGenerate = true)
public int uid;
#ColumnInfo(name = "text")
public String text;
#ColumnInfo(name = "timestamp")
public Long timestamp;
}
Anyway I still get get results with duplicates for field "text". How can I get a List that does not contains duplicates on field "text"?
For example if I have the following three elements in the database
database.addMyObject(new MyObject("dog", System.currentTimeInMills());
database.addMyObject(new MyObject("cat", System.currentTimeInMills());
database.addMyObject(new MyObject("dog", System.currentTimeInMills());
when I call my query I want to get only the first two elements.
If you want just list with unique text values you can try this one:
#Query("SELECT DISTINCT text FROM historyentity WHERE text LIKE :inputText || '%'")
List<String> findByText(String inputText); // <-- changed type to List<String>
UPDATE
You can try this query (it gets only one item with text value - with maximal id - or you can use maximal (or minimal) timestamp):
Select * from historyentity as t1
INNER JOIN (select text,max(uid) as uid from historyentity WHERE text LIKE :inputText group by text) t2
ON t1.text = t2.text and t1.uid = t2.uid

How to access columns of child entity with query while using room relation?

I have two entity order and customer. Each order is associated with zero or single customer and each customer is associated with zero or many orders.
#Entity
public class Order {
#PrimaryKey(autoGenerate = true)
public long id;
public long customerId;
....
}
#Entity
public class Customer {
#PrimaryKey(autoGenerate = true)
public long id;
public String name;
}
I wanted to query the order table with the corresponding customer if it exists.
So, I have created the relation following the documentation.
public class OrderAndCustomer {
#Embedded public Order order;
#Relation(
parentColumn = "customerId",
entityColumn = "id"
)
public Customer customer;
}
I can query the list of orders and the corresponding customer using dao.
#Dao
public interface OrderDao {
#Transaction
#Query("select * from `order`")
List<OrderAndCustomer> getOrderAndCustomer();
}
But when I try to access the columns of child entity, I got compile error. For instance, I wanted to query the order where customer name is like ****.
Therefore, my updated query:
#Query("select * from `order` where customer.name like '****'")
Is it possible to access the attribute of child entity in where clause?
So, the question arises that how the relation works!? I have figure out that it first query the order entity and then query the customer entity. Let me show the correct way If I am wrong.
I have another solution to query multiple tables but I am unable to use the relation feature what room provides or I am missing something!
I can follow this answer to use join and mapping to object.
public class OrderAndCustomer extends Order {
public String customerName;
}
Query:
#Query("select `order`.*, customer.name as customerName from `order` left outer join customer on `order`.customerId = customer.id where customerName like '****'")
List<OrderAndCustomer> getOrderAndCustomer();
But, Still have questions.
How do I map all columns of the order and customer table? Do I need to map all columns of customer with as in the query or there is another simplified approach available? If both tables has more columns and I need all of the columns of the first and second table to be fetched, then my query will be long enough. I wonder if there is the simplest thing to map both tables without or minimal using of as with all columns of the second table.
Help me with the right approach and better available solution.

How do I perform a Room DAO multi table join #Query using select fields?

My Problem:
I'm struggling to eliminate the compiling error on the following Room #Query statement in a Room DAO. As you can see, the SQLite query statement is joining various fields from different tables. The missing fields identified by the error are a part of the Notes class constructor identified in the List type for the method. I think I need to change the List type identified. If I'm right, I need some guidance/suggestion on how I should resolve it. Do I need to create a new Class and DAO with just those specific fields queried? Or maybe just a class since there is not table specific to these fields only. The error is:
error: The columns returned by the query does not have the fields [commentID,questionID,quoteID,termID,topicID,deleted] in com.mistywillow.researchdb.database.entities.Notes even though they are annotated as non-null or primitive. Columns returned by the query: [NoteID,SourceID,SourceType,Title,Summary]
List getNotesOnTopic(String topic);
#Query("SELECT n.NoteID, s.SourceID, s.SourceType, s.Title, c.Summary FROM Comments as c " +
"LEFT JOIN Notes as n ON n.CommentID = c.CommentID " +
"LEFT JOIN Sources as s ON n.SourceID = s.SourceID " +
"LEFT JOIN Topics as t ON n.TopicID = t.TopicID WHERE t.Topic = :topic AND n.Deleted = 0")
List<Notes> getNotesOnTopic(String topic);
What I'm trying to do:
I'm attempting to convert and existing Java desktop app with an embedded an SQLite database. The above query does work fine in that app. I only want to pass field data from these tables.
What I've tried:
I've done some googling and visited some forums for the last few days (e.g. Android Forum, Developer.Android.com) but most of the Room #Query examples are single table full field queries (e.g. "Select * From table"). Nothing I found yet (there is probably something) quite addresses how and what to do if you are joining and querying only specific fields across tables.
I think I may have fixed my issue. I just created a new class called SourceTable and designated the queried fields in the constructor. The only catch was I, according to a follow up error, was that the parameters had to match the field names.
public class SourcesTable {
private int NoteID;
private int SourceID;
private String SourceType;
private String Title;
private String Summary;
public SourcesTable(int NoteID, int SourceID, String SourceType, String Title, String Summary){
this.NoteID = NoteID;
this.SourceID = SourceID;
this.SourceType = SourceType;
this.Title = Title;
this.Summary = Summary;
}
}
and then I update my list method:
List<SourcesTable> getNotesOnTopic(String topic);

Android Room: Include Nested Object's Fields as Columns

Let's say I have a Patient entity, storing the patient ID, a boolean and finally a Person object. So I annotate these fields with #ColumnInfo to store in the database.
Now a Person has 2 String fields: a first name and last name.
However, in my patients table, I want to have a column directly for the first name and last name fields (from Person), and so I want to be able to call e.g. firstName (and not having to call Person.firstName) from a query. How may I achieve this?
You can use #Embedded annotation of Room for it.
In your case it will be as follows
public class Person {
String firstName;
String lastName;
}
public class Patient {
int patientId;//just an assumption
#Embedded
Person person;
}
For more information check this
Note : I haven't provided other annotations like #ColumnInfo for brevity

Android: using Realm to make a nested query?

I have a list of Teachers that each contain a list of Student objects. Each Student contains a list of schoolbooks that he has to bring each day. It looks like this:
Teacher {
String teacherName;
RealmList<Student> students = new RealmList<>();
}
Student {
String studentName;
RealmList<SchoolDay> schooldays = new RealmList<>();
}
SchoolDay {
String day;
RealmList<RealmString> schoolbooks;
}
(RealmString is simply primitive String wrapped as a RealmObject)
I want to extract the list of schoolbooks for a certain student on a certain day - several students might have the same schoolbooks, but I'm only interested in the books for one particular student on one particular day (for example, Sunday). A student might be in the classes of several teachers, but I'm only interested in the result for one of them as the weekly booklist will be different for each one. Sample query data might be:
teacher : steven
student : austin
day : sunday
This is where I get stuck - how do I subquery this? To get the teacher that I'm interested in:
RealmResults<Teacher> = realm.where(Teacher.class).equalTo("teacherName", "steven").findAll();
However, I then have to run a subquery on the teacher and a subquery on the student - or better yet, run all of them in the same query somehow. What I want to get as my final result is just the string representing the schoolbooks for that one particular student. How can I do this?
I would propose an easier option.
You can make use of inverse relationships:
The models will look like:
Teacher {
String teacherName;
RealmList<Student> students = new RealmList<>();
}
Student {
String studentName;
RealmList<SchoolDay> schooldays = new RealmList<>();
#LinkingObjects("students")
final RealmResults<Teacher> teacher = null;
}
SchoolDay {
String day;
RealmList<SchoolBook> schoolbooks;
#LinkingObjects("schooldays")
final RealmResults<Student> student = null;
}
SchoolBook {
String bookName;
#LinkingObjects("schoolbooks")
final RealmResults<SchoolDay> day = null;
}
And the query will be as simple as:
RealmResults<SchoolBook> = realm
.where(SchoolBook.class)
.equalTo("day.student.studentName", "austin")
.findAll();
Can you try like that :
realm.where(Teacher.class)
.equalTo("teacherName",teachername)
.equalTo("students.studentName",studentname)
.equalTo("students.schooldays.day",day).findAll();
After all you have Teacher object(s) and you can get variables in one query :
RealmResults<Teacher> teachers= your query above;
for(Teacher teacher:teachers){
//remember still you can have multiple students for given teacher
for(Student student:teacher.getStudents()){
for(Schoolday schoolday:student.getSchooldays()){
schoolday.schoolbooks bla bla bla...
}
}
}
Why we using for loop : because findAll() method can return multiple results, if you want single Teacher object use findFirst()
This will return you Teachers of given teachername attribute that contains/includes students with given student name : studentname and those students have schooldays with given: day name.
I think the last explaination is quite a bit hard to understand, now I explain it with examples:
In first query you are getting Teachers with name= "Yasin".
Assume that after this query you got 5 Teachers with name "Yasin".
Then in second query you are searching this 5 Yasin teachers; if their one of students name is "Jon". Assume that you have 3 Yasin teachers after that query.
Then in the last query you searching of that 3 "Yasin" teachers; if their one of students school day is "Sunday".
You can take a look at this question : how-to-make-a-nested-query-in-realm
Also this question is good for referencing ; it was helpful for me: realm-android-nested-query

Categories

Resources