【问题标题】:IndexedDB “and” and “or” queriesIndexedDB “and” 和 “or” 查询
【发布时间】:2019-08-06 19:04:16
【问题描述】:

我将以下内容存储在 IndexedDB 中:

[
  {
    name: 'pizza',
    ingredients: [ 'flour', 'water', 'yeast', 'salt', 'oil' ]
  }, {
    name: 'pasta',
    ingredients: [ 'semolina', 'salt', 'water' ]
  }, …
]

我在ingredients 上有一个multiEntry 索引:

store.createIndex('ingredientIdx', 'ingredients', { multiEntry: true });

现在,我想得到:

  1. 包含任何给定成分的膳食,例如flour water

  2. 包含所有给定成分的膳食,例如semolinasalt water

我的幼稚方法目前对每种给定成分执行多个查询,然后过滤和重复数据删除结果。但这感觉一点也不像“数据库”。

IndexedDB 是否支持某种“或”或“与”查询?这样做显然行不通

const tx = db.transaction('meals');
const ingredientIdx = tx.objectStore('meals').index('ingredientsIdx');
const request = ingredientIdx.getAll([ 'flour' , 'water' ]);
// …

【问题讨论】:

    标签: javascript indexeddb


    【解决方案1】:

    您已正确设置存储,并正确使用索引并且一次正确查询一个。您设置它的方式没有任何问题。但是,不幸的是,indexedDB 并不能轻松地以您想要的方式有效地查询该数据,例如通过使用单个光标/getAll 匹配多个对象。

    第一个问题是关于 OR 的使用。您不能在单个请求中执行此操作。您将需要执行多个请求。请注意,您至少可以同时执行这些请求。循环操作数并从多条目索引中获取每个操作数,将每个结果附加到每个请求共享的单个数组中,同时考虑重复项。您需要以这样的方式执行此操作,以便每个后续请求在开始之前不等待前一个请求完成。

    第二个问题是关于 AND 的使用。您只能对一系列值进行 AND 式查询,例如就像这个下限和上限之间的所有数字一样。因此,您需要一次查询一个,就像您现在一样。

    关于 AND,您可以考虑变得更聪明,并以不同的方式构造数据。例如,为每种成分创建布尔(使用 0 和 1)属性。例如。如果披萨有面粉,那么披萨对象有一个名为ingredient_flour 的属性值为1,如果披萨没有面粉,它要么没有属性,要么有属性ingrediant_flour,值为0。然后你可以创建不同成分组合的各种指标。例如。您可以在面粉和水上创建一个索引,然后在该索引中查询IDBKeyRange.only([1,1])

    并发 OR 示例(类似这样):

    function any(db, values) {
      return new Promise((resolve, reject) => {
        const objects = [];
        const transaction = db.transaction('meals');
    
        transaction.oncomplete = function(event) {
          resolve(objects);
        };
    
        transaction.onerror = function(event) {
          reject(event.target.error);
        };
    
        const store = transaction.objectStore('meals');
        const index = store.index('ingredients');
    
        function onsuccess(event) {
          const cursor = event.target.result;
          if (cursor) {
            const value = cursor.value;
    
            let exists = false;
            for (const object of objects) {
              if (object.name === value.name) {
                exists = true;
                break;
              }
            }
    
            if (!exists) {
              objects.push(value);
            }
    
            cursor.continue();
          }
        }
    
        for (const value of values) {
           // IDBKeyRange.only is implied in this next line
           const request = index.get(value);
           request.onsuccess = onsuccess;
        }
    
      });
    }
    

    【讨论】:

    • 非常感谢!我没有想到并行化的想法,好主意!
    猜你喜欢
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 2014-02-23
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多