Understanding Aggregation in Realm Java using Android Studio

in #utopian-io6 years ago (edited)

realmDark.jpg

Repository

https://github.com/realm/realm-java

What Will I Learn?

  1. How to use RealmConfiguration
  2. Realm Aggregation
    • sum()
    • min()
    • max()
    • average()
    • minDate()
    • maxDate()

Requirements

  • An Integrated Development Environment(IDE) for building Android Application(e.g Android Studio, IntelliJ)
  • Android Device/Virtual Device.
  • Little Experience in working with Realm Java.
  • Java Programming Experience.
  • Of course, willingness to learn

Resources

Difficulty

  • Intermediate
Tutorial Duration - 30 - 35Mins

Tutorial Content

In today's tutorial, we are going to be learning about aggregation in Realm.
In Realm, there are some default methods that in Realmm that makes performing mathematical operations on a RealmResult object easy based on a specific.

For instance, you have 8 Person objects that have the fields - name (String) , age (int) and sex (String) , we can find the oldest object using the max("age") method or the cummulation of the entire object's age by - sum("age").

And in our today's tutorial, we are going to be doing just that, we are going to be creating an android application have several objects and then we will be learning how to use this methods that are embedded in Realm.

Outline

  • Dependencied Used
  • Add a TextView in activity_main.xml layout file.
  • Create a model class - Person
  • Realm Aggregation Illustration

Depenedencies used

  • implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

The ButterKnife dependency should be placed in your application level gradle file - "build.gradle" which will make the injection of views (e.g ImageView, TextView) as easy as possible which we will be seeing in this tutorial.

  • implementation 'org.projectlombok:lombok:1.16.20'
    annotationProcessor 'org.projectlombok:lombok:1.16.20'

The lombok dependency also is placed in the application level gradle file which makes the generator of getter and setter methods for our model classes by just adding the annotations @Getter for getters and @Setter for the setter methods.

  • Realm dependency

    Steps

  1. Head to your project level gradle file and add the classpath dependency:
    classpath "io.realm:realm-gradle-plugin:5.1.0"

  2. Next, head to your application level Gradle file "build.gradle" and add the realm-android plugin to the top of the file.

apply plugin:'realm-android'

Finally, refresh your Gradle dependencies.

After you have added the necessary dependencies, your application level Gradle file should look like this :

app Gradle.PNG

And your project level Gradle file should look like this :

projectLevel.PNG

Add TextView in activity_main.xml

In order for us to show the result of our migrations in our tutorial, we are going to be adding one TextView in our activity_main.xml file :

<?xml version="1.0" encoding="utf-8"?>
//RootLayout - RelativeLayout

<TextView
    android:id="@+id/result"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="17sp"
    android:textColor="#000"
    android:text="Hello World!" />
        

Code Explanation
The above code includes a TextView in our layout file with the id - result and has a padding of 10 on every side - android:padding="10dp".

Creating the Person model Class

Next, we are going to create a new java class file which can be done by right-clicking on java folder => New => Java class and then input the name the class Person.

new java class file.PNG

Step 1

PersonClass.PNG

Step 2


Next, let the Person class extend the RealmObject class and add the following fields - name (String) , age (int) and then we add the annotations @Getter and @Setter using lombok in order to inject our getter and setter methods, this way boilerplate are eliminated.

@Getter
@Setter
public class Person extends RealmObject {
    private String name;
    private int age;
    private Date dateOfBirth;
}

Realm Aggregation Illustration

To illustrate Aggregation in Realm, we are going to be creating a Realm database that will be containing several Person realmm objects and then we are going to be querying the database to retrieve details such as the oldest person in the realm database by specifying the age field mostly.

Note: Aggration in Realm are carried out on a RealmResult object.

The Aggregation methods are explained thus:

  1. min() - takes a model field as the first argument (i.e age ) and returns the object having the smallest age.
  2. max() - Does the opposite of min() which returns the object with the highest age.
  3. sum() - takes a model field as its first argument (i.e age ) and returns the sum of all the age's returned in the RealResult object.
  4. average() - takes a model field as the first argument and returns the average of all the specified field in the RealmResult object.
  5. maxDate() - takes a Date model field as its first argument and then returns the object with the highest Date field.
  6. minDate() - does the opposite of maxDate().

MainActivity.java

Firstly, we have to create a Realm variable - private Realm realm; and then add the following codes in our onCreate() method

Realm.init(this);

RealmConfiguration customConfig = new RealmConfiguration.Builder()
                .name("aggregation.realm")
                .build()

realm = Realm.getInstance(customConfig);

createRealmObjects();

Code Explanation

  1. We initialize Realm in our Acitivy class file - Realm.init(this);
  2. We create a custom Realm configuration by the name - customConfig then we specify the name of our realm file as - aggregation.realm and not the default - realm.realm name and then lastly we call the build() method.
  3. We then call the createRealmObjects(); which as its name implies creates Realm Objects.

createRealmObjects()

private void createRealmObjects() {
realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            Person Paul = realm.createObject(Person.class);
            Paul.setName("Paul");
            Paul.setAge(27);
            Paul.setDateOfBirth(new Date("May 05, 2006"));

            //New Person Object Bola
            
            //New Person Object - Sam
   
            //New Person Object - Blessing

            //New Person Object - Isi
            
            //New Person Object - Samanta
        }
    });
    StringBuilder toDisplay = new StringBuilder();
        RealmResults<Person> results = realm.where(Person.class).findAll();
        
        int sum = results.sum("age").intValue();
        int min = results.min("age").intValue();
        int max = results.max("age").intValue();
        double average = results.average("age");
        
        Date maxDate = results.maxDate("dateOfBirth");
        Date minDate = results.minDate("dateOfBirth");

        Person youngest = results.where().equalTo("age",min).findFirst();

        Person oldest = results.where().equalTo("age",max).findFirst();

        Person firstCelebrator = results.where().equalTo("dateOfBirth",minDate).findFirst();

        Person lastCelebrator = results.where().equalTo("dateOfBirth",maxDate).findFirst();

        toDisplay.append("Statistics of Objects in our Database --- \n\n");

        toDisplay.append("The youngest Person is "+youngest.getName()+" with age : "+youngest.getAge()+" and DOB of "+youngest.getDateOfBirth()+"\n\n");

        toDisplay.append("The oldest Person is "+oldest.getName()+" with age : "+oldest.getAge()+" and DOB of "+oldest.getDateOfBirth()+"\n\n");

        toDisplay.append("The person with the earliest Date of Birth "+firstCelebrator.getName()+" with age : "+firstCelebrator.getAge()+" and DOB of "+firstCelebrator.getDateOfBirth()+"\n\n");

        toDisplay.append("The person with the lastest Date of Birth "+lastCelebrator.getName()+" with age : "+lastCelebrator.getAge()+" and DOB of "+lastCelebrator.getDateOfBirth()+"\n\n");

        toDisplay.append("The sum of all age's is "+sum+"\n\n");

        toDisplay.append("The average of all age's is "+average+"\n\n");

        resultTv.setText(toDisplay);

Code Explanation

  1. We start an executeTransaction() on our realm variable and then we override the execute() method where we create six new Person objects with the details
    • Object 1 (Paul) => name = Paul , age = 27 , dateOfBirth = May 05 2006
    • Object 2 (Bola) => name = Bola , age = 31 , dateOfBirth = June 06, 2001
    • Object 3 (Sam) => name = Samuel , age = 15 , dateOfBirth = Feb 02, 2010
    • Object 4 (Blee) => name = Blessing , age = 12 , dateOfBirth = Jan 01, 2008
    • Object 5 (Isi) => name = Israel , age = 19 , dateOfBirth = Dec 12, 2012
    • Object 6 (Samanta) => name = Samanta , age = 52 , dateOfBirth = Nov 11, 2011
  2. Next, we declear a StringBuilder object - toDisplay.
  3. We then get all the objects that are of Person class and store them in a RealResult object - results
  4. Next, we get the sum, min , max and average of the objects as below -
    • sum() : We call the sum() method on the result RealmResult object and specify the age field as the first argument indicate that we want it to return an integer value with - .intValue() which returns the sum of all the age's in the result object.
    • min() : We call the min() method on the result RealmResult object and specify the age field as the first argument indicate that we want it to return an integer value with - .intValue() which returns the smallest age value in the result object.
    • max() : We call the max() method on the result RealmResult object and specify the age field as the first argument indicate that we want it to return an integer value with - .intValue() which returns the highest age value in the result object.
    • average() : We call the average() method on the result RealmResult object and specify the age field as the first argument indicate that we want it to return an integer value with - .intValue() which returns the average of all the age's in the result object.
  5. We also get the maxDate and minDate as below
    • maxDate() : We call the maxDate() method on the result RealmResult object and specify the dateOfBirth field as its first argument and we do the same for the minDate but calling the minDate() method on the result RealmResult object.
  6. We then get the youngest , oldest , firstCelebrator and -lastCelebrator_ Person object as explained below -
    • youngest : We use the result object and get the youngest person in the result set by specifying the age field and the min int variable as the second argument with the findFirst() method which will return a Person object that is the youngest.
    • oldest : We use the result object and get the oldest person in the result set by specifying the age field and the max int variable as the second argument with the findFirst() method which will return a Person object that is the youngest.
    • firstCelebrator : We use the result object and get the person object that has the earliest DOB in the result set by specifying the dateOfBirth field and the minDate Date variable as the second argument with the findFirst() method which will return a Person object.
    • lastCelebrator : We use the result object and get the person object that has the last DOB in the result set by specifying the dateOfBirth field and the maxDate Date variable as the second argument with the findFirst() method which will return a Person object.
  7. We then display the details of all this Person object appending them to the - toDisplay StringBuilder object as below :
    • name : (i.e youngest.getName)
    • age : (i.e oldest.getAge)
    • dateOfBirth : (i.e firstCelebrator.getDateOfBirth)
  8. Lastly, we set the toDisplay StringBuilder object as the text of our TextView injected with ButterKnife - resultTv.setText(toDisplay);

Application Execution Image

Screenshot_20180606-001218.png

Curriculum

Proof of Work

https://github.com/generalkolo/Realm-Examples/tree/master/Realm%20Aggregation

Sort:  

Hey @edetebenezer
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Contributing on Utopian
Learn how to contribute on our website or by watching this tutorial on Youtube.

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

I see...
I really want to learn all of them.... Thank you darling... You are a good person.. . You're the best

Am glad you like it @asrinaphonna

Thank you for your contribution.
I liked overall the concepts discussed herein although a bit basic, but had few suggestions/questions:

  • Your code in the post actually did not include the code for inserting the different persons' info, only a comment to do so, while the github repo does include the code. How come?
  • You stored both age and dob. Is there not an easier way to just store one value (dob) and infer the age accordingly?
  • Your approach to storing repos in github doesn't look too proper to me. Your prior parts are located on a separate github repo, mixed together, while this one is separate. Try to make a single repo, with the different "parts" as sub-folders.
  • You've had few typos here and there in your work, nothing critical but at least a class name was mistyped and few other minor typos.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thanks @mcfarhat for taking out time to moderate my contribution.

Your code in the post actually did not include the code for inserting the different persons' info, only a comment to do so, while the github repo does include the code. How come?

Just thought I would reduce the length of the codes pasted so I showed in the comments that another object was created using the format of the one showed (object - Paul)

You stored both age and dob. Is there not an easier way to just store one value (dob) and infer the age accordingly?

I wanted to show the use of the maxDate and max differently that was why that was done.

Your approach to storing repos in github doesn't look too proper to me. Your prior parts are located on a separate github repo, mixed together, while this one is separate. Try to make a single repo, with the different "parts" as sub-folders.

I would rectify this accordingly

You've had few typos here and there in your work, nothing critical but at least a class name was mistyped and few other minor typos.

I would also look into this.

Thank you once again.

Congratulations @edetebenezer! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the total payout received

Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word STOP

Do you like SteemitBoard's project? Then Vote for its witness and get one more award!

Coin Marketplace

STEEM 0.18
TRX 0.14
JST 0.029
BTC 58068.07
ETH 3133.85
USDT 1.00
SBD 2.44