在 Dexie table 中搜索数组中的键

Search Dexie table for a key in an array

如果我在indexedDB/Dexietable中有如下记录:

{
  id: 1,
  name: "foo",
  children: [{id: 12, bar: "b"},
             {id: 14, bar: "c"}]
}

每个 child ID 都是唯一的。也就是说,只有 1 条记录的 child 给定 id 为 14.

  1. 如何在 children 上设置索引,以便我可以搜索包含 ID 为 14 的 child 的记录?
  2. 然后我如何最有效地搜索包含 child 且键位于 anyOf([3, 7, 9])
  3. 中的多条记录

看起来像:

  1. 只有Indexable Types可以用于多条目索引
  2. Edge 仍然不支持 indexed-db 标准的多入口键!!!坦率地说可笑。
  3. 允许原始问题中描述的行为 has been suggested

考虑将父数据冗余存储在子对象中。例如。 table 中的一个对象看起来像:

{
  "parent" : {
    "id": 1,
    "name": "foo",
  },
  "id": 12,
  "bar": "a"
}

然后您可以在 id 上创建索引。或者,因为child id是object key,所以其实不需要创建索引,可以针对object store的key路径进行查询。

但是,您不能执行 IN 样式查询。因为 IN 本质上是 shorthand for id = 1 or id = 2 or id = 3,这是一个联合,这是在 indexedDB 中做不到的。至少效率不高。在这种情况下,您需要做的是创建 3 个查询,每个查询一个,每个查询针对相同的索引(或对象存储的键路径),然后将结果合并到一个数组中。

IndexedDB 允许多条目索引,但仅限于简单数组,而不是 objects 的数组。但是你可以解决这个问题,方法是在一侧维护一个数组,其中包含所有包含的 id 和索引 属性 而不是:

{
  id: 1,
  name: "foo",
  children: [{id: 12, bar: "b"},
             {id: 14, bar: "c"}],
  childrenIds: [12, 14]
}
// Dexie schema:
const db = new Dexie("db");
db.version(1).stores({
  table: "++id, *childrenIds"
});

MultiEntry 索引适用于 Chromium、Firefox 和 Safari。 IE11 不支持,但即将推出的 Chromium-based Edge 浏览器会。

替代方法

另一种方法是以关系方式设计您的 table:

const db = new Dexie("relDB");
db.version(1).stores({
  parents: "++id",
  children: "++id, parentId"
});

Parent objects:

{
  id: 1,
  name: "foo",
}

Child objects:

{id: 12, bar: "b", parentId: 1}
{id: 14, bar: "c", parentId: 1}

然后,要根据一组 child 个 ID [12、14] 检索 parent,请对 children [=56= 使用 anyOf() 查询]:

const children = await db.children.where('id').anyOf([12, 14]).toArray();
const parentIds = new Set(children.map(child => child.parentId));
const parents = await db.parents.bulkGet([...parentIds]);

结论

我已经介绍了两种可选方法,它们都是解决您问题的有效方法。第一个选项是添加一个简单的 child ID 数组和使用 MultiEntry 索引的索引,另一个选项是将 children 放在单独的 table 中。如果您选择第二个选项,使用 dexie-relationships 插件查询包含 parents 的 children 或包含 parents 的查询也可能会有所帮助child含仁。

备注

我在 children 上索引 parentId 的原因是在关系模式中这样做是一个很好的做法,以便能够查询所有 children某些parent(此处不举例)。