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

Ari*_*zer 3 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){....};
Run Code Online (Sandbox Code Playgroud)

我知道如何按日期查询:

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

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


编辑-我想做的伪查询是

user_id=123 AND create_date < (NOW() - 24 * 60 * 1000)
Run Code Online (Sandbox Code Playgroud)

谢谢!

hag*_*wal 5

下面是一个工作示例。

<!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>
Run Code Online (Sandbox Code Playgroud)

解决您所遇到的问题的要点和概念:

  • 要求是从多个属性中搜索值,并且进行范围搜索。所以,你需要
    • 复杂/复合索引涵盖您要搜索的属性 ( 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 到 1031000 到 2000 之间的范围。它不是您指定的复杂/复合范围的 AND,而是 OR。

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