IDBObjectStore.createIndex()中keyPath的用途是什么?

Tom*_*ica 4 javascript indexeddb ecmascript-6 idbobjectstore

我一直在阅读有关MDN的内容,但是却得到如下内容

keyPath
要使用的索引的关键路径。注意,可以创建一个带有空值的索引keyPath,也可以将序列(数组)作为a传递keyPath

好吧,没有s @!t keyPath是关键路径。那是什么

在所有示例中,它与列名(或称其为索引)相同:

  objectStore.createIndex("hours", "hours", { unique: false });
  objectStore.createIndex("minutes", "minutes", { unique: false });
  objectStore.createIndex("day", "day", { unique: false });
  objectStore.createIndex("month", "month", { unique: false });
  objectStore.createIndex("year", "year", { unique: false });
Run Code Online (Sandbox Code Playgroud)

他们说您可以通过:

  • 空字符串- ""
  • 有效的JavaScript标识符(我认为这意味着有效的JS变量名称)
  • 多个JavaScript标识符,以句点分隔,例如: "name.name2.foo.bar"
  • 包含以上任何一个的数组,例如: ["foo.bar","","name"]

我无法想象这有什么目的。我绝对不明白这keyPath是什么,我可以用它做什么。有人可以提供示例用法,keyPath而不是列名吗?解释值keyPath对数据库有什么影响?

Jos*_*ell 5

示例可能会有所帮助。如果将键路径用于对象存储,则可以从存储的对象中拔出键,而不必在每次put()调用中都指定它们。例如,对于仅具有ID和名称的记录,可以将记录的ID用作对象存储库的主键:

store = db.createObjectStore('my_store', {keyPath: 'id'});
store.put({id: 987, name: 'Alice'});
store.put({id: 123, name: 'Bob'});
Run Code Online (Sandbox Code Playgroud)

这给您这家商店:

key   | value
------+-------------------
123   | {id: 123, name: 'Bob'}
987   | {id: 987, name: 'Alice'}
Run Code Online (Sandbox Code Playgroud)

但是,如果要按名称查找记录,可以创建一个索引:

name_index = store.createIndex('index_by_name', 'name');
Run Code Online (Sandbox Code Playgroud)

这给你这个索引:

key     | primary key | value
--------+-------------+--------------------------
'Alice' | 987         | {id: 987, name: 'Alice'}
'Bob'   | 123         | {id: 123, name: 'Bob'}
Run Code Online (Sandbox Code Playgroud)

(索引实际上并没有存储值的副本,而只是存储主键。但是这种方式更容易可视化。这也解释了如果迭代索引将在光标上看到的属性。)

现在,您可以使用以下名称按名称查找记录:

req = name_index.get('Alice')
Run Code Online (Sandbox Code Playgroud)

将记录添加到存储时,键路径用于生成索引的键。

带有.分隔符的键路径可用于在更复杂的记录中进行查找。数组的键路径可以生成复合键(其中键本身是数组),也可以生成多个索引条目(如果multiEntry: true已指定)


and*_*sit 5

理解事物的一个好方法是思考如何自己设计它。

让我们退后一步,看看一个非常简单的 NoSQL 数据库如何存储数据,然后添加索引。

每个 Store 看起来像一个 JavaScript 对象(或者 Python 中的字典,C# 中的哈希)等等......

{
  "1": {"name": "Lara", "age": "20"},
  "2": {"name": "Sara", "age": "22"},
  "3": {"name": "Joe", "age": "22"},
}
Run Code Online (Sandbox Code Playgroud)

这个结构基本上是一个值列表,加上一个索引来检索值,如下所示:

//Raw JS:
var sara = data["2"]
// IndexedDB equivalent:
store.get(2)
Run Code Online (Sandbox Code Playgroud)

这对于直接对象检索来说非常快,但对于过滤来说却很糟糕。如果你想得到特定年龄的人,你需要遍历每个值。

如果您事先知道您将按年龄进行查询,那么您可以通过创建一个按年龄索引值的新对象来真正加快此类查询的速度:

{
  "20": [<lara>],
  "22": [<joe>, <sara>],
  ...
}
Run Code Online (Sandbox Code Playgroud)

但是你会如何查询呢?您不能使用默认索引语法(例如data[22]store.get(22)),因为那些需要键。

一种方法是命名第二个索引,例如,by_age_index并为我们的商店对象提供一种按名称访问该索引的方法,因此您可以这样做:

store.index('by_age_index').get(22) // Returns Joe and Sara
Run Code Online (Sandbox Code Playgroud)

谜题的最后一点是告诉索引如何确定哪些记录与哪个键对应(因为在添加/更改/删除记录时它必须保持自身更新)

换句话说,它怎么知道 Joe 和 Sara 反对键 22,而 Lara 反对键 20?

在我们的例子中,我们想使用每条记录中的字段年龄。这就是我们所说的 keyPath。

因此,在定义索引时,我们指定索引和名称是有意义的,例如

store.createIndex('by_age_index', 'age');
Run Code Online (Sandbox Code Playgroud)

当然,如果你想像这样访问你的索引:

store.index('age').get(22) // Returns Joe and Sara
Run Code Online (Sandbox Code Playgroud)

然后你需要像这样创建你的索引:

store.createIndex('age', 'age');
Run Code Online (Sandbox Code Playgroud)

这就是大多数人所做的,这就是为什么我们在示例中看到的原因,这给人的印象是第一个参数是 keyPath(而实际上它只是我们给该索引的任意名称)让我们不确定第二个参数可能是什么为了。

我可以这样解释这一切:

第一个参数是您访问存储上索引的句柄,第二个参数是该索引应根据其对记录进行分组的记录上的字段名称。

但也许这个破败也会帮助其他人:-)