如何在IndexedDB中创建具有多个条件的查询

时间:2015-07-14 10:22:15

标签: javascript indexeddb

我有一个商店,我想查询多个索引。为了示例,我们假设我有一个带有user_id索引和create_date的消息存储,它是时间戳(并假设我有索引 - user_id / create_date / user_id,create_date

我知道如何通过id查询用户:

var range = IDBKeyRange.only('123');
store.index('user_id').openCursor(range).onsuccess= function(e){....};

我知道如何按日期查询:

var range = IDBKeyRange.lowerBound(Date.now()-24 * 60 * 1000))
store.index('create_data').openCursor(range).onsuccess = function(e){....};

购买我无法弄清楚如何一起查询。我知道我可以使用JS解析2中的任何一个的结果,但我想知道是否可以使用IDB来做到这一点。

编辑 - 我想要做的伪查询是

user_id=123 AND create_date < (NOW() - 24 * 60 * 1000)

谢谢!

2 个答案:

答案 0 :(得分:0)

答案是使用IDBKeyRange.bound

var range = IDBKeyRange.bound(['123'],['123', Date.now()-10*1000]);

store.index('user_id,create_date').getCursor(range).onsuccess = function(e){...}

基本上,所有IDBKeyRange范围都可以使用bound范围表示,因此通过使用多个值,我们可以创建任何我们想要的复合范围

答案 1 :(得分:0)

下面的工作示例。

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Stackoverflow</title>
    <script type="text/javascript" charset="utf-8">
            var db_handler = null;
            var dbDeleteRequest = window.indexedDB.deleteDatabase("toDoList");
            dbDeleteRequest.onerror = function(event) {
                console.log("Error while deleting database.", true);
            };

            dbDeleteRequest.onsuccess = function(event) {
                // Let us open our database
                var DBOpenRequest = window.indexedDB.open("toDoList", 5);

                DBOpenRequest.onsuccess = function(event) {
                  console.log('<li>Database initialised.</li>');

                  // store the result of opening the database in the db variable. This is used a lot below
                  db_handler = DBOpenRequest.result;

                  // Run the addData() function to add the data to the database
                  addData();
                };

                DBOpenRequest.onupgradeneeded = function(event) {
                  console.log('<li>DBOpenRequest.onupgradeneeded</li>');
                  var db = event.target.result;

                  db.onerror = function(event) {
                    console.log('<li>Error loading database.</li>');
                  };

                  // Create an objectStore for this database   //, { keyPath: "taskTitle" });  { autoIncrement : true }
                  var objectStore = db.createObjectStore("toDoList", { autoIncrement : true });

                  // define what data items the objectStore will contain

                  objectStore.createIndex("user_id", "user_id", { unique: false });
                  objectStore.createIndex("create_data", "create_data", { unique: false });
                  objectStore.createIndex("tags",['user_id','create_data'], {unique:false});
                };
            };

            function addData() {
              // Create a new object ready to insert into the IDB
              var newItem = [];
              newItem.push({ user_id: "101", create_data: (1000)});
              newItem.push({ user_id: "102", create_data: (Date.now() - 18 * 60 * 1000)});
              newItem.push({ user_id: "103", create_data: (Date.now() - 18 * 60 * 1000)});
              newItem.push({ user_id: "101", create_data: (2000)});
              newItem.push({ user_id: "101", create_data: (989)});
              newItem.push({ user_id: "104", create_data: (Date.now() - 18 * 60 * 1000)});

              console.log(newItem);

              // open a read/write db transaction, ready for adding the data
              var transaction = db_handler.transaction(["toDoList"], "readwrite");

              // report on the success of opening the transaction
              transaction.oncomplete = function(event) {
                console.log('<li>Transaction completed: database modification finished.</li>' + new Date());
              };


              transaction.onerror = function(event) {
                console.log('<li>Transaction not opened due to error. Duplicate items not allowed.</li>');
              };

              // create an object store on the transaction
              var objectStore = transaction.objectStore("toDoList");

              addData2(transaction, objectStore, newItem, 0, true);

            };

            function addData2(txn, store, records, i, commitT) {
              try {
                if (i < records.length) {
                  var rec = records[i];
                  var req = store.add(rec);
                  req.onsuccess = function(ev) {
                    i++;
                    console.log("Adding record " + i + " " + new Date());
                    addData2(txn, store, records, i, commitT);
                    return;
                  }
                  req.onerror = function(ev) {
                    console.log("Failed to add record." + "  Error: " + ev.message);
                  }
                } else if (i == records.length) {
                  console.log('Finished adding ' + records.length + " records");
                }
              } catch (e) {
                console.log(e.message);
              }
              //console.log("#########")
            };


            function select() {
                var transaction = db_handler.transaction('toDoList','readonly');
                var store = transaction.objectStore('toDoList');
                var index = store.index('tags');

                var range = IDBKeyRange.bound(['101', 999],['101', 2001]);

                var req = index.openCursor(range);

                req.onsuccess = function(e){
                    var cursor = e.target.result;
                        if (cursor) {
                            if(cursor.value != null && cursor.value != undefined){
                                console.log(cursor.value);
                             }
                            cursor["continue"]();
                        }
                }
            }
    </script>
</head>
<body>
    <div id="selectButton">
        <button onclick="select()">Select Data</button>
        <input type="text" id="selectData" value="">
    </div>
</body>
</html>

关键点和概念,以解决您的问题陈述:

  • 要求是从多个属性和范围边界搜索中搜索值。所以,你需要
    • 复杂/复合索引 ,涵盖您要搜索的属性(IDBObjectStore.createIndex()),以便您可以搜索多个媒体资源。
    • 基于范围的搜索 ,所以 - IDBKeyRange.bound()

在上面的例子中,

  • 使用objectStore.createIndex("tags",['user_id','create_data'], {unique:false});
  • 创建复杂或复合索引
  • 范围是使用var range = IDBKeyRange.bound(['101', 1000],['101', 2000]);
  • 创建的

提醒:
var range = IDBKeyRange.bound(['101', 1000],['101', 2000]);可以很好地满足您的需求,但请确保此var range = IDBKeyRange.bound(['101', 1000],['103', 2000]);

的结果

如果您使用的是复数/化合物范围,那么它的范围介于101到103 OR 1000到2000之间。它不是AND而是您指定的复数/化合物范围的OR。

尝试各种范围组合,您将了解IDBKeyRange的全部功能和限制。