如何使用 ydn-db-fulltext 在数组中索引子对象属性?
Posted
技术标签:
【中文标题】如何使用 ydn-db-fulltext 在数组中索引子对象属性?【英文标题】:How can I index child object properties in an array using ydn-db-fulltext? 【发布时间】:2014-04-29 06:56:59 【问题描述】:我正在使用 Ydn-Db-Fulltext 来允许用户在 html5 应用程序中搜索本地联系人数据库。到目前为止,在搜索人名时,它效果很好,很智能,并且可以立即返回结果。
这是一个包含联系人方法数组的联系人对象示例:
"source": "COMPANY",
"ownerPin": "12345",
"name": "brian wilkins",
"dateUpdated": "2014-03-18T14:41:05.217Z",
"dateAdded": "2014-03-18T14:41:05.217Z",
"isFavorite": false,
"socialId": "54321",
"id": "1",
"deleted": false,
"edited": false,
"favorite": false,
"contactMethods": [
"id": "4321",
"contactKey": "12321",
"contactId": "1",
"value": "brian.wilkins@geemail.com",
"kind": "email",
"ownerPin": "12345",
"isPrimary": false
,
"id": "5432",
"contactKey": "2",
"contactId": "1",
"kind": "phone",
"ownerPin": "12345",
"isPrimary": false
,
"id": "23",
"contactKey": "333",
"contactId": "1",
"value": "112345",
"kind": "extension",
"ownerPin": "12345",
"isPrimary": false
]
要在“名称”属性上创建索引,我将 fullTextCatalog 设置如下:
fullTextCatalogs: [
name: 'name',
lang: 'en',
sources: [
storeName: 'contacts',
keyPath: 'id',
weight: 1.0
,
storeName: 'contacts',
keyPath: 'name',
weight: 0.5
]
],
stores: [
name: 'contacts',
keyPath: 'id',
autoIncrement: true
]
;
this.db = new ydn.db.Storage('thedatabase', db_schema);
我可以按姓名或 id(键)搜索并获取匹配的联系人列表。似乎很少存储在内存中。每次搜索都会查询本地后备 indexedDB 数据库。
挑战在于,我还希望能够基于电子邮件地址和扩展名进行搜索,它们存储在contactMethods 数组中的contactMethods 属性中。 “value”属性是我们根据contactMethod类型存储电子邮件地址和/或扩展名的地方。
我尝试将contactMethods 添加为辅助可搜索对象存储,但这导致搜索“Brian”返回两个结果,包括包含姓名的联系人和包含电子邮件地址的contactMethod。理想情况下,我希望获取contactId(联系人的外键)并使用它来提取实际的联系人对象,但这似乎会产生非常昂贵的开销并抵消这个出色搜索工具的好处。
有没有办法索引不在父级的对象属性?我怎样才能以一种既能扩展又不会耗尽所有资源的方式来解决这个问题?
this.db.get(entry.storeName, entry.primaryKey).done(function(x)
this.textContent += ' [Full name: ' + x.name + ']'; // this is in the contact
this.textContent += ' [email: ' + x.value + ']'; // but this is in the contactMethod
, span);
【问题讨论】:
感谢@Kyaw 的标记帮助。我正在阅读schema documentation 更多内容,这听起来像是父->子一对多的关系,因为数组是我需要的,因为数组是我需要的,其中一个关键元素是名称和另一个是电子邮件地址,或类似的东西。如果我在别人之前弄清楚,我肯定会自我回答。 :) 【参考方案1】:有没有办法索引不在父级的对象属性?
keyPath
可以使用点分表示法来引用深层对象属性。例如,您可以指定 contactMethods.value
来索引电子邮件,但不幸的是它不适用于数组值 - 在这种情况下。
因此,显而易见的选择是使用父子关系将contactMethods
记录保存在单独的对象存储中。由于 ydn-db 目前不支持架构中的embedded
属性,因此您必须在加载父对象时加载所有子记录。
或者,IndexedDB v2 可能具有由函数表达式生成的虚拟索引。您可以在 ydn-db by generator
在索引架构中使用,例如:
stores: [
name: 'contacts',
keyPath: 'id',
autoIncrement: true,
indexes: [
name: '$emails',
multiEntry: true,
generator: function(record)
return record.contactMethods.map(function(x) return x.value;
)
]
]
但需要注意的是,生成的字段$emails
会在您加载数据时出现。它可能会从记录中删除,以便与 v2 规范匹配。
我们在多个项目中大量使用这个生成器索引,所以我会修复错误。
在全文搜索中索引id
和电子邮件地址很方便,但没有意义,因为基于语音的全文搜索将在没有规范化的情况下对它们进行索引。
【讨论】:
我不确定我是否理解您所说的关于 $emails 出现和被删除的意思。我看到了索引,但里面什么都没有。我在生成器中放了一个 console.log 语句,我可以看到 x.value 有数据。这是必须等待您所指的错误修复的东西吗?谢谢! 没有错误,生成器正在工作。您必须在全文目录源中指定$emails
。如果您发现错误,请提交问题。
好的,所以我不知道 Chrome 是否使用 indexedDB v2。我可以告诉生成器正在运行,但即使 $emails 在 fullTextCatalog 中,索引也没有被填充。所以我假设这是因为 Chrome 不使用 indexedDB v2。因此,这一定意味着我必须使用选项 1,即为contactMethods 创建一个单独的存储。通过查看 ydn-db 源,我假设 generate 应该只是将索引属性添加到父对象,以便 ydn-db 可以填充索引?我尝试使用带有逗号分隔的电子邮件列表的单个“电子邮件”属性手动尝试,
[cont'd] 但我不确定搜索是否能够正常工作,因为无法进行完全匹配。
是的。要按前缀键查询,请使用IndexValueIterator.where('store name', '$email', 'starts', 'prefixkey')
以上是关于如何使用 ydn-db-fulltext 在数组中索引子对象属性?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 MongoDB 在数组中的对象中更新数组中的对象中的文档?