tekartik / sembast.dart

Simple io database
BSD 2-Clause "Simplified" License
763 stars 64 forks source link

Bulk Update support #9

Closed fvisticot closed 5 years ago

fvisticot commented 5 years ago

Is it possible to make a bulk update based on a query / filter ? By example setting active value to true for all records with macAddress = '123'

alextekartik commented 5 years ago

It is not possible at the moment. But it could be implemented efficiently in a transaction (using a transaction is the key to make it fast, especially when the changes are commited) by finding records and updating them 1 by one.

The API does not support 'patching' a record neither to update a single field.

Let's keep this issue open as I think they both deserve solution that I need to think about. Thanks!

fvisticot commented 5 years ago

If update is not available... how to update fields (even in a transaction) ? Do I need to make a get -> to get the record, delete it, and ad it again ?

alextekartik commented 5 years ago

As i said you cannot update a single field (I'm currently looking at that). You can update the whole record however using:

put({'macAddress': '00:11:22:33:44:55'}, key)

To update a single field for now, the solution is:

await db.transaction((txn) async {
  // read
  record = await txn.getRecord(key);
  // update one field
  record['macAddress'] = '00:11:22:33:44:55';
  // write
  await txn.putRecord(record);
});
alextekartik commented 5 years ago

I have publish 1.10.0 that allows updating only some fields of a record, similarly to firestore.set. Some documentation here: https://github.com/tekartik/sembast.dart/blob/master/doc/writes.md#updating-fields

store.update({'macAddress': '00:11:22:33:44:55}, key);

Bulk update is not supported yet. You still have to query first (you can query keys only) then update each record one by one (which is very fast in a transaction)

fvisticot commented 5 years ago

Using 1.10.0 I have made some tests to update a record field : This code is working: await store.update({'flushed': true}, 89);

This code is working:

await _db.transaction((txn) async {
        var store = txn.getStore('beacons');
        store.update({'flushed': true}, 148);
      });

When I try to loop over multiple records it does not work:

await _db.transaction((txn) async {
        var store=txn.getStore('beacons');
        List<Future> futures = List();
        recordsIds.forEach((key) => futures.add(store.update({'flushed': true}, key)));
        await Future.wait(futures);
      });

I get this error in the logs:

flutter: FINE: 2018-11-06 23:56:53.030405: txn 2 get null key 9
flutter: FINE: 2018-11-06 23:56:53.031026: txn 2 get null key 10
flutter: FINE: 2018-11-06 23:56:53.032141: txn 2 get null key 11
flutter: FINE: 2018-11-06 23:56:53.032805: txn 2 get null key 12
flutter: FINE: 2018-11-06 23:56:53.033639: txn 2 get null key 13

How to update multiple records in a transaction coming from a list of keys ?

alextekartik commented 5 years ago

Thanks for the report. I could not reproduce the issue. I tried it here and it worked as expected:

https://github.com/tekartik/sembast.dart/blob/3ab915d013bd78006812b7ad38fc23fad68073b2/test/exp_test.dart#L55-L70

Do you have a unit test that you could easily extract?

fvisticot commented 5 years ago

Sorry, it was an issue on my side.. I was using a key of type int for storing and requesting with a key of type String ... It works now !!

alextekartik commented 5 years ago

I added in 1.10.1 the utility function updateRecords although it is only a few lines of code. See https://github.com/tekartik/sembast.dart/blob/master/doc/writes.md#bulk-update