3

I am stuck in one case of firebase operation in android. My Requirement :

I have table Named : "Values" This value table contains following type of data.

  {
    "menu": [
             {
               "category": "cocktails",
               "product": [
                            {
                              "id": "123",
                              "name": "test1"
                            },
                            {
                              "id": "456",
                              "name": "test2"
                            }
                          ]
            },
            {
               "category": "vodka",
               "product": [
                            {
                               "id": "789",
                               "name": "test3"
                             },
                             {
                                "id": "901",
                                "name": "test4"
                             }
                         ]
              }
           ]
       }

Now, I want to update id : 123 with name = "test5" , How to update this nested array object in firebase database in android?

I tried following but it update/add Entire menu array not perticular product array object.

I just want to update in product array object.

Following are the code that i tried, but it update all menu array.

      val listPorduct = ArrayList<HashMap<String, Any>>()

      for ((i, product) in productList.withIndex()) {

            var productMap = HashMap<String, Any>()

              productMap = hashMapOf(
                "id" to "123",
                "name" to "test5")

             listPorduct.add(productMap)
       }

        val map = hashMapOf<String, Any>()
        map.put("category", list[position].category)
        map.put("product", listPorduct)

       repository.getTabs().update("menu", FieldValue.arrayUnion(map))

if i am try with

       repository.getTabs().update("menu/product", FieldValue.arrayUnion(map))

       or

       repository.getTabs().update("menu.product", FieldValue.arrayUnion(map))

then getting issue / or dot not allowed. i have latest firebase gradle file.

How update particular position of product object? Please anyone can help me to solve out this?

Image of firebase database.

enter image description here

Topsy
  • 177
  • 17
  • https://stackoverflow.com/questions/59611061/firestore-add-element-in-a-field-in-hashmap this is not an answer – Jenis Kasundra Jan 07 '20 at 13:47
  • we need to update array inside an array please give a solution for this question – Jenis Kasundra Jan 07 '20 at 13:49
  • @AlexMamo: While the question you linked shows a similar problem, it is often helpful for devs to see how to apply it to their own problem. I highly recommend leading a comment when closing dupes on how to apply the linked answer to their problem. I'm also not convinced the linked answer is the best answer for all cases. Storing the sub-elements in a sub-collection is a valid approach, but storing them in the same document can be valid too. I'm voting to reopen the question, allowing others to answer with the actual code of how to update the nested/array field. – Frank van Puffelen Jan 07 '20 at 14:09
  • @FrankvanPuffelen Ya, my bad for not leaving a comment, I usually do. Now, I just answered this question with some details regarding this specific use-case. However, storing the sub-elements in a sub-collection was just another solution besides the initial one. Thanks again puf. – Alex Mamo Jan 07 '20 at 14:45
  • 1
    Also see: https://stackoverflow.com/questions/46757614/how-to-update-an-array-of-objects-with-firestore/46773121#46773121 – Frank van Puffelen Jan 07 '20 at 15:08
  • @FrankvanPuffelen if we use Option 2(subcollection) then we need to update all the item individually. we can not update the items in a single call of firestore. – Jenis Kasundra Jan 08 '20 at 11:22

1 Answers1

4

The solution to this problem can be found in my answer from the following post:

There is a slightly smaller difference. However, for your use-case, please note that the document that you gave us as an example contains a property named menu which is of type array. In this array, you have added some objects that contain two properties, a String property named category and an array named product. This array contains in term two other properties, one is the id and the other one is the name, both being of type String.

None of those arrays can be updated using FieldValue.arrayUnion(map). The only option that you have is to get the menu array as a list of HashMap<String, Any>. Once you have this map, you can simply iterate through it and get the desired data.

So to update the value of a property inside a Map, you should first get the map, do the changes and put it back. In the end, after you've done all the necessary changes, write the document back to Firestore.

Edit:

According to your comment:

In my case I have more than 5000 records in a list with a nested array.

It's hard to believe that you can nest 5000 elements into a single document because it might not fit since the maximum size for a document is 1 MiB (1,048,576 bytes). Please see usage and limits. So nesting 5000 objects into an array isn't a solution at all. In this case, the single solution that you have is to use a sub-collection and add each item from the array as a document. In this case, there are no limitations.

As a conclusion, the only highly scalable way to store an unknown large list of items is using documents in a collection. Array type fields do not scale for lists the are constantly growing because the items will eventually exceed that (1 MiB), which will obviously cause problems in the future.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • so we need to make menu array as a list of HashMap with changes and write back menu to document. – Jenis Kasundra Jan 07 '20 at 14:56
  • is there any other way to update a particular ArrayList's item within other ArrayList? – Jenis Kasundra Jan 07 '20 at 15:00
  • @JenisKasundra This is how you need to get it. If in the `menu` array would have been strings, then the OP could get that array as a List. In that particular case, he could also use `FieldValue.arrayUnion` but not in this use-case. – Alex Mamo Jan 07 '20 at 15:00
  • @JenisKasundra There is currently no other way. – Alex Mamo Jan 07 '20 at 15:01
  • @AlexMamo In My case i have more than 5000 record in list with nested array , So, for update single record out of 5000+ record, its good idea to do? Please can you more clarify with android code syntax how to achieve these? firebase is so much complex to handle large amount of data, there is no any easy way to handle it? – Topsy Jan 08 '20 at 11:10
  • Hello @AlexMamo, As per your answer, we change the database table structure and used sub-collection, just one query that, we are updating data using "batch write", We are updating data based on user selection in list, means user select 500 records to update ( as our requirement user select multiple record and set hit out of stock button, so all record in list make out of stock ), So, there is proper way to update this? and second query is that while we updating this number of data, its take 4 to 5 seconds to udpate, So this is normal time or little bit more time to udpate? – Topsy Jan 10 '20 at 07:49
  • *So, there is a proper way to update this?* It should be but this is not a question that can be answered in a comment. So for that, please post another fresh question using its own [MCVE](https://stackoverflow.com/help/mcve), so I and other Firebase developers can help you. – Alex Mamo Jan 10 '20 at 07:53
  • @AlexMamo please can you give this answer so its save my time to asking another question. While we updating these number of data (400-500), its take 4 to 5 seconds to udpate, So this is normal time or little bit more time to udpate ? – Topsy Jan 10 '20 at 07:55
  • You are asking a question that it is far too complex from being reasonable to answer in a comment. That's why I requested you to ask another question along with an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example) as it not enough context. – Alex Mamo Jan 10 '20 at 07:58
  • @AlexMamo ok thanks for help, your answer help me to solve my problem, so upvote it. And please help like this to other people so they get answer before closing the questoin :) – Topsy Jan 10 '20 at 08:00
  • Ok, got it ;) Thanks – Alex Mamo Jan 10 '20 at 08:01