16

I can a data to the Firebase Firestore document through the following methods:

1) add()

2) set()

I am very clear that how can i add data to Firestore, there is no confusion in it. But my question there is two setOption for the method 'set' in Firebase Firestore, such that merge and mergefields. What is the difference between these two set options, I think both options are doing same job. How can I implement setOption 'mergeFIeld'? I can't find any documentation for it.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Dev
  • 1,308
  • 3
  • 13
  • 24

3 Answers3

28

This is how I interpreted it. IF merge = true is specified to a set operation THEN it is like Object.assign(firestoreDoc, yourpayload). For example, if firebaseDoc contents are like this:

{
  name:'batman',
  city: 'gotham',
  isLeagueMember: true
}

And your payload (JSON) content is like this:

{
  isLeageMember:false,
  reason:'gone rogue'
}

After the set operation with merge=true the firestoreDoc will look like

{
  name:'batman',
  city: 'gotham',
  isLeagueMember: false,
  reason:'gone rogue'
}

On the other hand, for mergeFields you would specify the set of fields to update. So if I take the above example but this time set operation with merge fields options [name, reason] then the result (firebaseDoc after set completion) will be:

{
  name:'batman',
  city: 'gotham',
  isLeagueMember: true,
  reason:'gone rogue'
}

This was somewhat confusing to me too until I found the biggest clue is merge is a boolean and mergeFields is an array.

This is very handy for batched operations.

Hope this helps. Thank you.

harrisonlo
  • 564
  • 1
  • 5
  • 18
Ali Nahid
  • 867
  • 11
  • 26
  • 3
    What the doc and this answer don't make clear is that `mergeField` option is only relevant if the `merge` option is set to `true`. It's an option that modifies the behavior of another option if you will. – Louis Ameline Apr 02 '22 at 15:25
  • @LouisAmeline Is this actually true? I'm trying to peer into the source code to confirm, but I'm having trouble. Can you provide a source for this? (Additional context: an `assert` in `set_options.dart` XORs the 2 arguments, implying only 1 is acceptable.) – Ross Llewallyn May 15 '23 at 22:50
  • @RossLlewallyn I asked the Firebase team to come up with this answer. I've worked a lot on a fork of a library called Vuex Easy Firebase, that's why I had to know. – Louis Ameline May 16 '23 at 06:11
5

One important thing to note; { merge: true } has a somewhat strange interaction if you ask me. If an inner object is empty, it will replace the existing inner object. However if it's not empty, it will update the specified property in the inner object and leave the rest alone.

E.g. set({ innerObject: {}, { merge: true })

to existing { innerObject: { someKey: 'someValue' } }

would result in { innerObject: {} }

However

set({ innerObject: { someOtherKey: 'someOtherValue' }, { merge: true })

to existing { innerObject: { someKey: 'someValue' } }

would result in { innerObject: { someKey: 'someValue', someOtherKey: 'someOtherValue' } }

So make sure to clean out empty inner objects unless you want to delete them from the document.

Bumpfel
  • 61
  • 1
  • 3
-4

As you already noticed, when using DocumentReference's set() function, you are allowed to pass as the second argument either SetOptions's merge:

Changes the behavior of a set() call to only replace the values specified in its data argument. Fields omitted from the set() call remain untouched.

Or SetOptions's mergefields:

Changes the behavior of set() calls to only replace the specified field paths. Any field path that is not specified is ignored and remains untouched.

Both are optional, but both change set to act as a Merge/Upsert instead of overwriting all fields not provided in the data parameter. This will create the document from the document reference if it does not exist, and otherwise performs the behavior of update.

SetOptions.Merge will merge based on the object keys you specify in its data parameter. SetOptions.MergeFields is a bit more awkward. It's easy to skim right over the documentation description, but it states that the array of field paths you specify will be the only ones taken from the data parameter when updating values. Meaning not all the key-values passed in the data parameter are used in the merge operation.

Think of mergeFields as picking key-values from the provided data and applying those in your operation. It's not really necessary, and just is a shorthand for cleaning up the key values and passing into merge. Note, it will not delete fields omitted in data that are declared in the field path array, instead you just get a firebase error that a field path is missing from your input data. It seems like explicit FieldValue.delete is the only option for that behavior.

For nested field paths you do get some additional benefit. You can more explicitly control the update operation.

ex. For document name: { first: 'Jon', last: 'Doe' }


set({ name: { first: 'Jane' } }, { merge: true });

becomes

name: { first: 'Jane', last: 'Doe' }


set({ name: { first: 'larry' } }, { mergeFields: ['name.first'] })

also becomes

name: { first: 'Jane', last: 'Doe' }


set({ name: { first: 'larry' } }, { mergeFields: ['name'] })

unlike the others becomes

name: { first: 'Jon' }

where the field path is replaced.

Harry Scheuerle
  • 377
  • 2
  • 15
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • I think Mergefield is only for nested fields..?can you please show me an example,if you don’t minds – Dev Apr 27 '19 at 11:08
  • You should make your own attempt given the informations and see the behavior yourself. – Alex Mamo Apr 27 '19 at 12:10
  • Ok i will try..but can you please give me explanation of about mergefield is only for nested fields.? – Dev Apr 27 '19 at 12:38
  • Add the docs states, its for nested properties and any field path that is not specified is ignored and remains untouched. – Alex Mamo Apr 27 '19 at 12:40
  • 4
    This answer does not address what the documentation doesn't make clear: what happens with values in the data argument that are not specified in the mergefields when there is no existing record in firestore – nbransby Jan 06 '20 at 18:20
  • @nbransby This answer is **not** meant to make the documentation clear, it is added to answer OP's question, who was seeking for documentation. See this sentence? *I can't find any documentation for it.* – Alex Mamo Jan 08 '20 at 14:21
  • 1
    Sorry, but I too don't find this answer very helpful. Doesn't explain anything more than the docs, which itself is not very descriptive. – Shailesh Appukuttan May 13 '20 at 20:23