开始使用 PouchDB - 第 3 部分





5.00/5 (1投票)
在本系列文章的第三篇中,您将学习如何在 PouchDB 数据库中查询数据。
引言
在 CodeProject.com 上的前两篇文章中,您已经了解了 PouchDB NoSQL 数据库。
在这两篇文章中,您学会了创建新数据库、修改数据库中的文档以及使用 allDocs()
检索文档。现在您已经向 PouchDB
数据库插入了几份文档,您可能希望根据 _id
属性以外字段中的数据来检索文档。在我们关于 PouchDB
的系列文章的第三部分中,您将学习使用 find()
插件对文档中的任何属性执行查询。
Mango 查询
pouchdb-find
插件可在 GitHub 上下载。find()
方法,也称为 Mango
,是一种结构化查询机制,允许您创建用于执行搜索的二级索引。此方法对于回答以下问题非常有用:查找 lastName
等于 'sheriff
' 的所有文档,或 cost
大于 75
的文档。下载 pouchdb.find
插件并将链接添加到 pouchdb-find.js 文件。此链接应放在 pouchdb-xxxxx.js 文件链接之后。
<script src="../Scripts/pouchdb-6.4.3.min.js"></script>
<script src="../Scripts/pouchdb.find.js"></script>
创建索引
您不必对要查询的字段创建索引,但如果不创建,则会扫描所有文档。根据数据库中文档的数量,这可能是一项非常昂贵(且缓慢)的操作。如果您知道最常查询的字段,请在这些字段上创建索引。下面的代码示例说明了如何为 lastName
属性创建索引,并为 cost
属性创建另一个索引。
function createIndexes() {
// Create index on last Name
db.createIndex({
index: {
fields: ['lastName']
}
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
// Create index on cost
db.createIndex({
index: {
fields: ['cost']
}
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
请注意,fields
属性是属性名称的数组。您可以指定一组要索引的字段。例如,您可能希望首先按 lastName
字段索引,然后按 firstName
字段索引。
无索引时排序错误
如果您尝试对未索引的字段进行排序,您将收到 PouchDB
的错误。如果 selector
中使用的字段没有索引,则使用默认索引(_id
字段),并执行完整文档扫描。PouchDB
无法在字段没有索引的情况下排序数据,因此您会收到错误。
function showError() {
// NOTE: Create an index on the sort field or you get an error
db.find({
selector: { firstName: 'Paul' },
sort: ['firstName']
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
运行上述函数时收到的错误消息是
Error: Cannot sort on field(s) "firstName" when using the default index
无索引时警告
如果您在选择器中使用字段且没有可用的索引,则会在数据库中执行完整的文档扫描。数据将返回带有适当选定文档的结果,但您会收到一条警告,提示未找到匹配的索引。然后,您可以决定是否要创建一个。
function showWarning() {
// NOTE: You get an error if you use a property name in the 'selector' that is not indexed
db.find({
selector: { firstName: 'Paul' }
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
收到的响应对象如下所示
{
"docs": [
{
"firstName": "Paul",
"lastName": "Sheriff",
"docType": "technician",
"_id": "psheriff",
"_rev": "1-36a6815e79f54819bc0b4ee3bd435aa1"
}
],
"warning": "no matching index found, create an index to optimize query time"
}
查找姓氏
您之前已在 lastName
字段上创建了索引。现在,您可以通过在 selector
属性中将 lastName
指定为字段之一来使用该索引。您可以通过包含 fields
属性来进一步限定返回的内容。此属性是文档中您希望从此查询返回的属性名称数组。如果需要,您可以包含 sort
属性,但实际上没有必要。当使用索引时,文档会按索引顺序返回。
function findLastName() {
db.find({
selector: { lastName: 'Sheriff' },
fields: ['_id', 'firstName', 'lastName'],
sort: ['lastName']
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
上述查询的结果如下所示
{
"docs": [
{
"_id": "msheriff",
"firstName": "Madison",
"lastName": "Sheriff"
},
{
"_id": "psheriff",
"firstName": "Paul",
"lastName": "Sheriff"
}
]
}
查找多个姓氏
除了精确匹配搜索之外,您还可以使用许多选择器运算符。选择器运算符以美元符号 ($
) 为前缀,包括:$eq
、$gt
、$gte
、$lt
、$lte
、$in
。
创建一个函数,使用 $in
运算符来查找文档中多个姓氏。下面的代码显示了搜索姓氏匹配 'Sheriff
' 或 'Jones
' 的内容。
function findLastNames() {
pouchDBSamplesCommon.hideMessageAreas();
db.find({
selector: {
lastName: { $in: ['Sheriff', 'Jones'] }
},
fields: ['_id', 'firstName', 'lastName']
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
上面查询的返回结果如下所示。请注意,此选择器运算符不使用基于姓氏字段的索引。某些类型的运算符并非总是能够使用索引;$in
、$or
和 $regex
是其中一些不能使用的。
{
"docs": [
{
"_id": "bjones",
"firstName": "Bruce",
"lastName": "Jones"
},
{
"_id": "msheriff",
"firstName": "Madison",
"lastName": "Sheriff"
},
{
"_id": "psheriff",
"firstName": "Paul",
"lastName": "Sheriff"
}
],
"warning": "no matching index found, create an index to optimize query time"
}
查找成本大于 75
另一个有用的选择器运算符是大于 ($gt
)。您之前已在 docType
为 'service
' 的文档的 cost
属性上创建了索引。使用以下代码查找所有成本大于 75
的服务
function greaterThan() {
pouchDBSamplesCommon.hideMessageAreas();
db.find({
selector: { cost: { $gt: 75 } },
fields: ['_id', 'cost']
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
搜索两个字段
您不限于只为单个字段建立索引。您可以在索引的 fields
属性中包含两个或多个字段。在 selector
属性中,您现在可以指定两个要匹配的字段。在下面的示例代码中,您正在查询文档,查找 doctype
等于 'service
' 且 cost
大于 75
的文档。
function searchTwoFields() {
// Create index on two fields
db.createIndex({
index: {
fields: ['docType', 'cost']
}
}).then(function (response) {
// Search on two fields
return db.find({
selector: {
docType: 'service',
cost: { $gt: 75 }
},
fields: ['_id', 'cost']
});
}).then(function (response) {
pouchDBSamplesCommon.displayJSON(response);
}).catch(function (err) {
pouchDBSamplesCommon.displayMessage(err);
});
}
摘要
在本系列关于 PouchDB
的第三部分中,您学习了如何使用 find()
方法。此方法是 PouchDB
的一个插件,因此您必须单独下载它。find()
方法允许您搜索文档中 _id
字段以外的字段。请务必为要搜索的字段创建索引,因为这样做可以提高搜索性能。在下一篇文章中,您将学习如何使用 query()
方法和 map
函数。