我们可以在Flutter Web中使用Dart在indexedDb上创建索引吗?

huangapple go评论87阅读模式
英文:

Can we have index on indexedDb using dart in flutter web?

问题

我尝试在Flutter Web中实现Hive,但发现它不支持添加索引。底层的indexedDb支持添加index,但Hive不支持(至少我找不到任何示例或文档)。

我尝试使用idb_shim来实现,它有关于向数据库添加索引的官方文档。

当我尝试使用idb_shim向indexDb添加Dart对象时,它会抛出错误UnimplementedError: structured clone of other type,对于某些条目。以下是添加的代码:

IdbFactory idbFactory = getIdbFactory();
_db = await idbFactory.open(boxName,
  version: 1, onUpgradeNeeded: this.onUpgradeNeeded);
var txn = _db.transaction(boxName, idbModeReadWrite);
var store = txn.objectStore(boxName);
await store.put(value, key);
await txn.completed;

类似地,当我尝试读取对象时,它以ArrayBuffer的形式存在,而不是JSON对象。没有文档明确说明如何在indexedDb中存储/读取Dart对象。

var txn = _db.transaction(boxName, idbModeReadOnly);
var store = txn.objectStore(boxName);
final value = await store.getObject(key);
print(value); // ArrayBuffer

await txn.completed;
return value as T; // 转换为实际Dart对象时会抛出错误
  • 我们是否需要使用dart:js包将Dart对象转换为JavaScript对象?

  • 我们是否需要将对象存储为字符串化的JSON字符串?在这种情况下,索引可能不起作用?

英文:

I have tried implementing Hive for flutter web, but found out that it doesn't provide adding indexes. The underlying indexedDb provided adding index but Hive doesn't provide (at least I couldn't find any example or docs)

I am trying to implement idb_shim, which has official docs for adding index to database.

When I am trying to add a dart object to indexDb using idb_shim it throws an error UnimplementedError: structured clone of other type for some entries. Following is code to add

      IdbFactory idbFactory = getIdbFactory();
      _db = await idbFactory.open(boxName,
        version: 1, onUpgradeNeeded: this.onUpgradeNeeded);
      var txn = _db.transaction(boxName, idbModeReadWrite);
      var store = txn.objectStore(boxName);
      await store.put(value, key);
      await txn.completed;

Similarly, when I am trying to read the object, it is in form of ArrayBuffer not the JSON object. There is no docs indicating clearly on how to store/read dart objects in indexedDb.

      var txn = _db.transaction(boxName, idbModeReadOnly);
      var store = txn.objectStore(boxName);
      final value = await store.getObject(key);
      print(value); // ArrayBuffer

      await txn.completed;
      return value as T; // throws error when converting to actual dart-object
  • Do we need to convert dart-objects to Javascript Objects using dart:js package?

  • Do we need to store the object in stringified JSON string? In this case index may not work?

答案1

得分: 0

我已找到解决方案:

我们是否需要使用dart:js包将Dart对象转换为JavaScript对象?

是的,我们需要创建不同的对象,使用以下语法:

import 'package:js/js.dart';

@JS()
@anonymous
abstract class JsItem {
  external bool get prop1;
  external int get prop2;
  external String get prop3;
  external String get bulk_data;

  external factory JsItem({int prop2 = 0, String prop3 = '', String bulk_data = '', bool prop1 = false});
}

在插入到IndexedDB时,您可以插入对象JsItem()

我们是否需要将对象存储为字符串化的JSON字符串?在这种情况下,索引可能无法工作?

我已经克服了这个问题,通过将大多数数据(除了索引属性)转换为JSON字符串并插入到bulk_data中。在这里,prop1prop2prop3是索引属性。

读取数据

indexedDB中读取数据时,它以LinkedList映射的格式呈现,所有属性都可以作为map属性读取。因此,创建一个类似下面的辅助函数会很有帮助:

  toDartItem(LinkedMap map){
    return DartItem({ prop1: map["prop1"], 
     prop2: map["prop2"], 
     prop3: map["prop3"], 
     bulk_data: map["bulk_data"], // 根据需要将JSON转换为不同的属性
    )};
  }
英文:

I have found solution to both issues:

Do we need to convert dart-objects to Javascript Objects using dart:js package?

Yes, we need to create different objects with following syntax:

import 'package:js/js.dart';

@JS()
@anonymous
abstract class JsItem {
  external bool get prop1;
  external int get prop2;
  external String get prop3;
  external String get bulk_data;

  external factory JsItem({int prop2 = 0, String prop3 = '', String bulk_data = '', bool prop1 = false});
}

While inserting to IndexedDB you can insert the object JsItem().

Do we need to store the object in stringified JSON string? In this case index may not work?

I have overcome of this issue by converting most of data (excluding indexes properties) to JSON string and inserting into bulk_data. Here prop1, prop2, prop3 are indexes.

Reading the data

While reading the data form indexedDB it comes in format of LinkedList map and all properties can be read as map properties. So it would be helpful to create a helper function like below:

  toDartItem(LinkedMap map){
    return DartItem({ prop1: map["prop1"], 
     prop2: map["prop2"], 
     prop3: map["prop3"], 
     bulk_data: map["bulk_data"], // Convert JSOn to different props as required
    )};
  }

huangapple
  • 本文由 发表于 2023年7月27日 18:38:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定