Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.59k stars 597 forks source link

handle when Preparecreate or Prepareupdate #1528

Open gabrielporcher opened 1 year ago

gabrielporcher commented 1 year ago

I don't have much experience with relational databases, so I have a question that might be stupid.

I come from many years of development with Realm. In the realm, if I try to create a new record with the same id passing the modified prop, an automatic update is performed instead of create. I didn't find anything similar in the watermelon documentation, so my question is the following: Every day when opening the app my users receive a list of areas. With this list, the following batch is created:

await database.write(async () => {
          await database.batch(
            ...subareasOrdened.map(item => database.get('subarea').prepareCreate(data => {
              data.psId = item.psId
              data.cropName = item.cropName
              data.grower = item.grower
              data.subSystemName = item.subSystemName
              data.systemName = item.systemName
              data.systemType = item.systemType
              data.colorL1 = item.colorL1
              data.colorL2 = item.colorL2
            }))
          )
        })

My question is whether I should treat this batch and try to update it before creating it or shoul I just do this way and everything will works fine?

gabrielporcher commented 1 year ago

Just updating: It doesn't work. It creates multiple same areas (even with same psId).

Reading the docs I assumed that the code should be something like:

//subareasOrdened is an array with all my response areas from api
        const existingAreas = await database.get('subarea').query().fetch();

        const areasToUpdate = subareasOrdened.filter(item => existingAreas.some(item2 => item2.psId === item.psId))
        const areasToCreate = subareasOrdened.filter(item => !existingAreas.some(item2 => item2.psId === item.psId))

        console.log('areas to update: ', areasToUpdate.length)
        console.log('areas to create: ', areasToCreate.length)
        await database.write(async () => {
          await database.batch(
            ...areasToUpdate.map(item => database.get('subarea').prepareUpdate(data => {
              data.cropName = item.cropName
              data.grower = item.grower
              data.subSystemName = item.subSystemName
              data.systemName = item.systemName
              data.systemType = item.systemType
              data.colorL1 = item.colorL1
              data.colorL2 = item.colorL2
            })),
            ...areasToCreate.map(item => database.get('subarea').prepareCreate(data => {
              data.cropName = item.cropName
              data.grower = item.grower
              data.subSystemName = item.subSystemName
              data.systemName = item.systemName
              data.systemType = item.systemType
              data.colorL1 = item.colorL1
              data.colorL2 = item.colorL2
            }))
          )
        })

I don't know why but I keep getting some errors due to prepareUpdate:

LOG [TypeError: undefined is not a function (near '..._repositorywdb.database.get('subarea').prepareUpdate...')]

Any help?

erickalvesduobox commented 1 year ago

@gabrielporcher

The prepareUpdate should be used on a model, it does not exist in the collection, you can change your code to map over the models in the existingAreas.

Hashir524 commented 1 year ago

Any Solution? Stuck in same problem?