IndexedDB模糊搜索

28

首先,对于我的英语表示抱歉。

我正在开发一个Web项目,在输入框中输入内容时会提示建议,但我想使用IndexedDB来提高Firefox中的查询速度。

使用WebSQL,我有以下语句:

db.transaction(function (tx) {
  var SQL = 'SELECT "column1", 
                    "column2" 
             FROM "table"
             WHERE "column1" LIKE ?
             ORDER BY "sortcolumn" DESC
             LIMIT 6';

  tx.executeSql(SQL, [searchTerm + '%'], function(tx, rs) {
    // Process code here
  });
});

我想用IndexedDB来做同样的事情,我有这段代码:

db.transaction(['table'], 'readonly')
  .objectStore('table')
  .index('sortcolumn')
  .openCursor(null, 'prev')
  .onsuccess = function (e) {
    e || (e = event);
    var cursor = e.target.result;
    if (cursor) {
        if (cursor.value.column1.substr(0, searchTerm.length) == searchTerm) {
            // Process code here
        } else {
            cursor.continue();
        }
    }
};

但是这个方法太慢了,而且我的代码有漏洞... 我想知道是否有更好的方法。

谢谢回复。

3个回答

30

我最终找到了解决这个问题的方法。

解决方案是将键范围限制在搜索词和以'z'字母结尾的搜索词之间。例如:

db.transaction(['table'], 'readonly')
  .objectStore('table')
  .openCursor(
    IDBKeyRange.bound(searchTerm, searchTerm + '\uffff'), // The important part, thank Velmont to point out
    'prev')
  .onsuccess = function (e) {
    e || (e = event);
    var cursor = e.target.result;
    if (cursor) {
      // console.log(cursor.value.column1 + ' = ' + cursor.value.column2);
      cursor.continue();
    }
  };

因为我需要对结果进行排序,所以在交易之前我定义了一个数组,然后在加载所有数据时调用它,就像这样:

var result = [];
db.transaction(['table'], 'readonly')
  .objectStore('table')
  .openCursor(
    IDBKeyRange.bound(searchTerm, searchTerm + '\uffff'), // The important part, thank Velmont to point out
    'prev')
  .onsuccess = function (e) {
    e || (e = event);
    var cursor = e.target.result;
    if (cursor) {
      result.push([cursor.value.column1, cursor.value.sortcolumn]);
      cursor.continue();
    } else {
      if (result.length) {
        result.sort(function (a, b) {
          return a[1] - b[2];
        });
      }

      // Process code here
    }
  };

1
非常感谢!这让我的程序从3500毫秒缩短到了140毫秒。 - pimvdb
@pimvdb 很高兴知道你觉得它有用。我添加了更多关于排序结果的示例。 - Fong-Wan Chau
7
最好使用\uffff作为您的标记,而不是z。如果您使用z,当搜索“wiki”时,您将无法获得“wikipædia”这样的搜索结果... - odinho - Velmont
你如何在搜索词的开头使用通配符?以下代码会返回错误:IDBKeyRange.bound('\uffff' + searchTerm, searchTerm + '\uffff')。 - Anonymoose
2
很抱歉,没有办法在搜索词的开头使用通配符。 - Fong-Wan Chau

3

我一直在尝试使用IndexedDB,发现它非常慢,加上其API的复杂性,我不确定是否值得使用。

这真的取决于你有多少数据,但可能值得在内存中搜索,然后你可以将数据从某种存储(无论是indexedDB还是更简单的localStorage)中解组和重新组合。


好像对于Internet Explorer和Firefox,我必须使用简单的XMLHttpRequest,因为XHR+PHP甚至更快。如果WebSQL成为标准就太好了,这样客户端将能够使用速度更快、更有效的Web应用程序,而服务器也将在长期内节省资源。 - Fong-Wan Chau

2

我在同一个问题上浪费了近2小时,最终找到了真正的问题。

以下是解决方法:

  • IDBCursor.PREV替换为prev (虽然很糟糕,但这是解决方法)

IDBCursor.PREV目前在Chrome上存在漏洞(截至2013年2月26日)。


好的,你遇到的问题和我遇到的不一样。你的问题是由于新规范(2013年2月20日更新)上的更改引起的:https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html。附注:我刚刚更新了我的问题和答案以匹配新规范。 - Fong-Wan Chau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接