How to compare two fields in android realm.io - android

Model:
public class Something extends RealmObject {
private String firstField;
private String secondField;
This is my query:
RealmResults<Something> r = realm.where(Something.class)
.notEqualTo("firstField","secondField")
.findAll();
is this correct and will give me all the records where the two fields are different? or will it give me all the records where firstField is not equal to the String "secondField"?
If it is incorrect, how do I achieve the comparing of the two fields?

Christian from Realm here. It is the second option. That query will compare the field "firstField" to the string "secondField". Unfortunately there is no easy way to do what you want, but it is probably not a uncommon use case so it is something we will take a look at how to support more easily.
Currently you would have to do it by hand:
RealmResults<Something> r = realm.where(Something.class)
.notEqualTo("firstField","secondField")
.findAll();
for (Something obj : r) {
if (!obj.getFirstField().equals(obj.getSecondField())) {
// Handle object
}
}

Related

Create words from random characters using the sqlite database

Let's just say I have the variable String SRand = "KELRSFGLIU", what I want to do is create a word from the SRand variable and search for that word in the database. Or looking for data in a database based on the SRand variable, the words that need to be found do not have to be 10 characters but can be 3, 4 - 10 characters
can this be done?
As an illustration, I want to do something like this:
Ilustration 1:
String SRand = "KELRSFGLIU";
String Suggestion = "";
private void Create_Suggestion(){
//The magic for creating Sugeestion in here
//The result can be "FIRE", "GLUE", "FUR", or something else.
Suggestion = ???;
SearchData(Suggestion);
}
private void SearchData(String Suggest){
//Data Must Be Found
}
Any Idea?
I suggest you use trees in case you want to do that, more info can be found here

Android Room - How to migrate when a nested object model is changed?

I have a database schema set up using Android Room, Dao, and Entity classes set up as POJOs. Except the POJO entity isn't so "plain" and that it actually holds a reference to another object. I thought this was a great idea at the time as it allowed me more flexibility in changing the object and using it in other places in the app and only saving to the database as needed.
The problem I'm facing now is that the migration guideline only mentions how to migrate the database by altering the SQL, but I changed the object itself. My typeconverter class simply converts the object to and from a string.
Because it's being saved as a long string I know I essentially have to do a simple REPLACE(string, old_string, new_string) in the SQL
migration code block with the updated object being the new string. How can I retrieve the old objects and update values before running the replace SQL command in the migration block?
UPDATE: I'm using GSON in my typeconverter class to change the object to a string, so the solution that comes to mind is to simply download the old object and upload the new one with the added fields. Only problem is that you can't access the database and download the json, convert it to the object, add the new data fields, then reconvert to a new json string.
I'm lucky I'm not at scale yet because this would be a tricky thing to do for so many users. (So I recommend that anyone reading this not do what I did and implement object nesting. It's easier to convert the Entry objects to the other portable objects instead of nesting when it comes to updating the data you want saved.)
I think if you already did what I did and can't go back, the best bet is to simply create the new portable object and make new typeconverter functions for that one and add the SQL COLUMN for the new object. The problem then lies in how you then retrieve those objects from the Entry Dao, which will cause a lot more code to write and possible errors to debug if not done carefully.
Long story short, if anyone is reading this, DO NOT nest objects in Room DBs on Android unless you are 100% sure it's a final form of your model... but is there such a thing anyways?
I just ran into this issue, but fortunately I only needed to add a new key/value pair to a "flat" object model. So hopefully my answer can be expanded on to fully answer #Mr.Drew question.
Assuming you have a table town with a column star_citizen that is the object model being typeconverted:
{"name":"John", "age":30, "car":false}
and you want to update the object to have an extra property "house": true
you could add a migration to your App's Room Database class like this (Kotlin example):
#Database(entities = [Town::class], version = 2, exportSchema = true)
#TypeConverters(DataConverters::class)
abstract class AppDatabase : RoomDatabase() {
abstract val sharedDao : SharedDao
companion object {
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
val cursor = database.query("SELECT * FROM `town`")
// iterate through each row in `town`, and update the json
// of the StarCitizen object model
cursor.moveToFirst()
while (!cursor.isAfterLast) {
val colIdIdx = cursor.getColumnIndex("id")
val id = cursor.getInt(colIdIdx)
val colStarCitizenIdx = cursor.getColumnIndex("star_citizen")
val rawJson = cursor.getString(colStarCitizenIdx)
val updatedRawJson = starCitizenModelV1ToV2(rawJson)
database.execSQL("""UPDATE town SET star_citizen ='${updatedRawJson}' WHERE ID = $id""")
cursor.moveToNext()
}
}
}
//[...]
private fun starCitizenModelV1ToV2(rawJson: String): String {
val rawJsonOpenEnded = rawJson.dropLast(1)
val newProperty = "\"house\":true"
return "$rawJsonOpenEnded,$newProperty}"
}
}
}

DC2type on greenDao

I am using GreenDao for Android application, with some specification, for example, I have a Contact Model with some information like name, avatar, phone number, etc...
Right now the need is to change from only one phone number to a multiphone number.
Instead of creating two tables (table for numbers, and table for contacts), I really need just one information is the number so in my backend the contact numbers is stocked on a DC2type, (a json array saved as a string).
Do we have a possibility to do that using GreenDao?
i search for a solution or a DC2type implementation , etc ... and nothing is found
so i decide to created by my self , and this is what i did :
using the #Convert annotation presented of GreenDao 3 :
#Property(nameInDb = "phoneNumbers")
#Convert(converter = PhoneNumbersConverter.class, columnType = String.class)
private List<String> phoneNumbers;
static class PhoneNumbersConverter implements PropertyConverter<List<String>, String> {
#Override
public List<String> convertToEntityProperty(String databaseValue) {
List<String> listOfStrings = new Gson().fromJson(databaseValue,List.class);
return listOfStrings;
}
#Override
public String convertToDatabaseValue(List<String> entityProperty) {
String json = new Gson().toJson(entityProperty);
return json;
}
}
short story long , i create a json to array parser
thanks to myself to helped me :D

Firebase Database change node ID

How can I change the naming of the nodes of my children in the image below?
questions_stats is a List<Integer>, I'm aware that I get integers as nodes Id because this is a List. I create each of the children randomly with a number between 0 and 1000. I set this ID as part of the object and to find it I loop trough the list. What I want is to set the "0671" as the Key of the Object at the moment I create it.
How should I define my object in order to access each child with an Id that I define as a String.
Each of the questions_stats is an object.
This is my UserProfile Class definition.
public class UserProfile implements Parcelable {
private List<Integer> questions_list;
private List<QuestionsStats> questions_stats;
private String country_name, share_code, user_name;
private int token_count;
private Boolean is_guest;
public UserProfile() {
}
public UserProfile(List<Integer> questions_list, List<QuestionsStats> questions_stats, String country_name, String share_code, String user_name, int token_count, Boolean is_guest) {
this.questions_list = questions_list;
this.questions_stats = questions_stats;
this.country_name = country_name;
this.share_code = share_code;
this.user_name = user_name;
this.token_count = token_count;
this.is_guest = is_guest;
}
}
I know I can set them using the child("0159").setValue(QuestionStats) individually.
But for my purpose I need to retrieve the data of the "user" as a whole and then iterate whithin questions_stats like it is a List.
How should I define my UserProfile class in order to achieve what I want?
Anybody could give me a hint?
How can I change the node names of my children in the image below?
Answer: There is no way in which you can change the names of the nodes from your Firebase database. There is no API for doing that. What can you do instead is to attach a listener on that node and get the dataSnapshot object. Having that data, you can write it in another place using other names. You cannot simply rename them from 0 to 0000, 1 to 0001 and so on.
Perhaps I should have asked for How to "Set" the node Id instead of "Change"
What I have is an List<QuestionsStats>, but when using an List<QuestionsStats> you get indexes as Keys, What I want is to have the same List<QuestionsStats> but instead of indexes, String Keys for each of my items.
So I changed my List for a Map<String, QuestionsStats>. Now the tricky part is when parceling the Object. You can use readMap() or writeMap() to parcel as shown here in this answer by #David Wasser, but it gives a warning:
Please use writeBundle(Bundle) instead. Flattens a Map into the parcel
at the current dataPosition(), growing dataCapacity() if needed. The
Map keys must be String objects. The Map values are written using
writeValue(Object) and must follow the specification there. It is
strongly recommended to use writeBundle(Bundle) instead of this
method, since the Bundle class provides a type-safe API that allows
you to avoid mysterious type errors at the point of marshalling.
So with the help of the comments in This Question I parceled using this code, note that I'm leaving the "easy" way commented in case somebody find it useful or have any comment on that :
protected UserProfile(Parcel in) {
// in.readMap(myMap, Object.class.getClassLoader());
myMap = new HashMap<>();
String[] array = in.createStringArray();
Bundle bundle = in.readBundle(Object.class.getClassLoader());
for (String s : array) {
myMap.put(s, (Object) bundle.getParcelable(s));
}
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// dest.writeMap(myMap);
Bundle bundle = new Bundle();
for (Map.Entry<String, Object> entry : myMap.entrySet()) {
bundle.putParcelable(entry.getKey(), entry.getValue());
}
Set<String> keySet = myMap.keySet();
String[] array = keySet.toArray(new String[keySet.size()]);
dest.writeStringArray(array);
dest.writeBundle(bundle);
}
Why I want this, well at the moment my list contains less than 100 items but it could grow up to a 1000, I'm no Pro, but I believe that if I already know the key of the item I'm interested in will be always better than having to iterate over the list to find it. In the end my main problem was the usage of a Map, I did not know howto.

ormlite DataType.ENUM_STRING gives me "is not valid for data persister"

Hello i am using ORMLite 4.33.
I have an entity class that gives me an error when trying to destroyTable:
E/AndroidRuntime(6715): java.lang.IllegalArgumentException: Field class
java.lang.String for field FieldType:name=udm,class=Prodotti is not valid
for data persister com.j256.ormlite.field.types.EnumStringType#40a3a2e0
here is the class
#DatabaseTable(tableName = "Prodotti")
public class Prodotti extends BaseDaoEnabled{
....
#DatabaseField(dataType = DataType.ENUM_STRING,
columnDefinition="VARCHAR(100) DEFAULT NULL")
//also tried #DatabaseField(dataType = DataType.ENUM_STRING)
private String udm;
...
}
I runned DatabaseConfigUtil to update the ormlite_config.txt, right now i'm thinking the only solution is to change the type of the field to String
ORMLite does not support database SQL enum columns which are only supported by a couple of database types. The ENUM_STRING is supposed to persist an enum type. Something like:
#DatabaseField
private OurEnum udm;
...
public enum OurEnum {
RED, GREEN, BLUE;
}
By default, ORMLite will then persist the enum as it's string value (RED, GREEN, BLUE) in a VARCHAR SQL field. If you have a String field then you should just let it be persisted as a STRING type. You can also use the DataType.ENUM_INTEGER if you want to store its value instead but that is not recommended for backwards compatibility reasons.
If you edit your questions to better explain what you are trying to accomplish, I can edit my answer to provide more information.

Categories

Resources