I am trying to perform FieldValue.arrayUnion() on set(), but it is throwing an Exception. I'm using set instead of update, because I want it to create the document if not exists.
Code (in my case its Batch Write, but I think the principle is same)
WriteBatch batch = db.batch();
MyModel myModel = new MyModel("rwTEPzn9vjyhZCZxFeq8", "Mangesh"); // sample data
batch.set(docRef, FieldValue.arrayUnion(myModel), SetOptions.mergeFields("items")); // throws exception
Stack trace:
W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firestore.v1.Value$ValueTypeCase com.google.firestore.v1.Value.getValueTypeCase()' on a null object reference
W/System.err: at com.google.firebase.firestore.UserDataReader.convertAndParseDocumentData(com.google.firebase:firebase-firestore@@21.4.2:233)
W/System.err: at com.google.firebase.firestore.UserDataReader.parseMergeData(com.google.firebase:firebase-firestore@@21.4.2:87)
W/System.err: at com.google.firebase.firestore.WriteBatch.set(com.google.firebase:firebase-firestore@@21.4.2:89)
W/System.err: at com.abc.AbcActivity.addTrans(AbcActivity.java:604)
W/System.err: at com.abc.AbcActivity.validateInputs(AbcActivity.java:571)
W/System.err: at com.abc.AbcActivity.onAddRecord(AbcActivity.java:260)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at android.view.View$DeclaredOnClickListener.onClick(View.java:5989)
W/System.err: at android.view.View.performClick(View.java:7140)
W/System.err: at android.view.View.performClickInternal(View.java:7117)
W/System.err: at android.view.View.access$3500(View.java:801)
W/System.err: at android.view.View$PerformClick.run(View.java:27351)
W/System.err: at android.os.Handler.handleCallback(Handler.java:883)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:100)
W/System.err: at android.os.Looper.loop(Looper.java:214)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7356)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
UPDATE 1: MyModel is a very simple POJO class with couple of strings.
public class MyModel {
private String id, name;
public MyModel (String id, String name) {
this.id = id;
this.name = name;
}
@PropertyName("id")
public String getId() {
return id;
}
@PropertyName("id")
public void setId(String id) {
this.id = id;
}
@PropertyName("name")
public String getName() {
return name;
}
@PropertyName("name")
public void setName(String name) {
this.name= name;
}
}
UPDATE 2: The exception is thrown for String and int values as well. That is, neither FieldValue.arrayUnion("abc") nor FieldValue.arrayUnion(1) works. I have also observed the same behaviour in case of arrayRemove().
UPDATE 3: Here is a screenshot of my db.

UPDATE 4: I tested set outside of batch, directly on the document. It fails. Note that items was emptied before doing this to avoid any type-related conflicts.
docRef.set(FieldValue.arrayUnion("abc"), SetOptions.mergeFields("items"));
Looks like it is impossible to use arrayUnion and arrayRemove with set, despite of the documentation that says: "returns a special value that can be used with set() or update()"
Finally, I found a solution. Here is the code:
Map<String, Object> map = new HashMap<>();
map.put("items", FieldValue.arrayUnion(myModel));
batch.set(docRef, map, SetOptions.merge());
This creates the document if not exists and updates items array. Note that, SetOptions.merge() is used instead of SetOptions.mergeFields().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With