javascript - 如何使用 ydn-db-fulltext 为数组中的子对象属性建立索引?

标签 javascript full-text-search indexeddb full-text-indexing ydn-db

我使用 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
    }
   ]
  }

为了在“name”属性上创建索引,我按如下方式设置 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);

最佳答案

Is there a way to index object properties that are not at the parent level?

keyPath 可以使用点分符号来引用深层对象属性。例如,您可以指定 contactMethods.value 来索引电子邮件,但不幸的是它不适用于数组值 - 正如本例所示。

因此,显而易见的选择是使用父子关系将 contactMethods 记录保存在单独的对象存储中。由于 ydn-db 目前不支持 schema 中的 embedded 属性,因此在加载父对象时必须加载所有子记录。

或者,IndexedDB v2可能具有由函数表达式生成的虚拟索引。您可以在索引架构中通过 generator 在 ydn-db 中使用,例如:

 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 和电子邮件地址很方便,但没有意义,因为基于语音的全文搜索将按原样对它们进行索引,而无需标准化。

关于javascript - 如何使用 ydn-db-fulltext 为数组中的子对象属性建立索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22566708/

相关文章:

javascript - 删除 HTML 标签和格式化文本

javascript - React useEffect 一次性获取 firestore 数据

javascript - 使用 .csv 文件数据填充 IndexedDB

javascript - IndexedDB 读取在写入完成之前完成

javascript - 在 Chrome 中使用带有本地文件的 iframe

javascript - IE vendor 前缀/非前缀转换翻译不工作

c# - 用于查找文本中所有关键字的高效算法

c++ - 使用整数列表文档进行全文搜索的最佳方法

lucene - Neo4j - 使用 Lucene 查询

javascript - indexedDB objectStore.get() 总是返回 undefined,尽管在 DB 中有结果