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

时间:2014-03-21 18:26:06

标签: 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属性中。 "值" property是我们存储电子邮件地址和/或扩展名的地方,具体取决于contactMethod类型。

我尝试将contactMethods添加为辅助搜索对象存储,但这导致搜索" Brian"返回两个结果,包括名称的联系人和包含电子邮件地址的contactMethod。理想情况下,我希望将contactId(外键用于联系人)并使用它来提取实际的联系对象,但似乎这会产生非常昂贵的开销,并否定了这个优秀搜索工具的好处。 / p>

有没有办法索引不在父级别的对象属性?我怎样才能以一种可以扩展并且不会占用所有资源的方式来解决这个问题呢?

  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);

1 个答案:

答案 0 :(得分:1)

  

有没有办法索引不在父级别的对象属性?

keyPath可以使用点分表示法来引用深层对象属性。例如,您可以指定contactMethods.value来索引电子邮件,但不幸的是它不能用于数组值 - 就像在这种情况下一样。

因此,显而易见的选择是使用父子关系将contactMethods记录保存在单独的对象存储中。由于ydn-db当前不支持模式中的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规范匹配。

我们在多个项目中大量使用此生成器索引,因此我将修复bug。

在全文搜索中索引id和电子邮件地址很方便,但没有意义,因为语音库全文搜索会将其编入索引,因为它没有规范化。