Javascript IndexedDB-计数值出现次数?
我正在为一本在线日语词典开发一个chrome扩展,我正在尝试记录和显示用户的查询统计数据,以便他知道自己最缺少的日语词汇 因此,我打算展示过去X天中被质疑最多的汉字(日语字符)。所以我在扩展indexedDB中用汉字/日期对和自动编码键创建了一个简单的对象存储,但似乎没有办法在indexedDB中执行这些查询 是使用游标并使用javascript回调按日期过滤和计数事件的唯一方法吗 编辑:用于创建数据库的代码Javascript IndexedDB-计数值出现次数?,javascript,google-chrome-extension,indexeddb,Javascript,Google Chrome Extension,Indexeddb,我正在为一本在线日语词典开发一个chrome扩展,我正在尝试记录和显示用户的查询统计数据,以便他知道自己最缺少的日语词汇 因此,我打算展示过去X天中被质疑最多的汉字(日语字符)。所以我在扩展indexedDB中用汉字/日期对和自动编码键创建了一个简单的对象存储,但似乎没有办法在indexedDB中执行这些查询 是使用游标并使用javascript回调按日期过滤和计数事件的唯一方法吗 编辑:用于创建数据库的代码 const DB_NAME = "kioku" const DB_VERSION =
const DB_NAME = "kioku"
const DB_VERSION = 1;
const KANJI_STORE = "kanji";
var db;
(function() {
var request = window.indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = function(e) {
db = e.target.result;
var kanjiStore = db.createObjectStore(KANJI_STORE, { autoIncrement: true });
kanjiStore.createIndex("date", "date", { unique: false });
}
})();
通过事件处理程序添加数据
function newRecentKanjiHandler(request, sender, sendResponse) {
/* ...stuff before this point was irrelevant so I removed it */
var kanjiStore = db.transaction([KANJI_STORE], "readwrite").objectStore(KANJI_STORE);
kanjiStore.add({kanji: request.kanji, date: Date.now()});
}
带有示例数据的屏幕截图
在本例中,我想显示如下内容
x3: 杉
x2: 刀, 尻
x1: 刃
对于用户。在我按日期范围过滤后,只需简单地计算发生次数,在本例中我没有这样做,因为时间戳在一小时之内,我的目的是过滤最后几天或几周。我喜欢这个问题。我肯定有人会有一个比我更好的答案,但这里是一个随机的尝试 首先,我应该指出一个旁白,您将在尝试将event.target.result分配给db时遇到问题。您试图将仅在其作用域内有效的对象推入外部作用域。这只会在以后给你带来麻烦。我建议学习更多关于JavaScript中异步函数的知识 第二,我将从当前方向后退一步开始,回顾关于您试图解决的问题的一些基本假设。有时indexedDB不是最好的解决方案。不幸的是,使用indexedDB迫使您尽早地面对这些设计问题 是否需要存储每个关键事件?如果不是,那么问题的规模就局限于不同汉字键的数量,而不是事件的数量。您可以完全放弃使用indexedDB,而使用一个简单的对象,将其持久化到本地存储 如果规模有点大,那么确定存储事件的目的是为了提问,还是为了其他目的?如果它只是你自己问题的目的,那么考虑改变你所存储的(模式)只解决它的特定目的,而不是其他目的的未知列表。 例如,如果它只是为了这个目的,并且不需要扩展,那么可以完全避免indexedDB,而只使用本地存储。如下所示:
function onCharEvent(char) {
var obj = JSON.parse(localStorage.KANJI_STATS || '');
var bar = obj[char] || {char: char, count: 0};
bar.count++;
bar.lastObserved = Date.now();
obj[char] = bar;
localStorage.KANJI_STATS = JSON.stringify(obj);
}
Kanji char | Count | Last observed
----------------------------------
char1 | 1 | 1234123412345
char2 | 2 | 4643563456345
char3 | 3 | 3245234523452
如果该特性仅用于此目的,并且必须是大规模的,则可以简化模式。首先想象一下,在完成所有分组、排序和计数之后,查询的类似列表的结果应该是什么样子。然后考虑如何在这个模式中执行add和put操作。如果我理解正确,您希望获得一组如下所示的结果:
function onCharEvent(char) {
var obj = JSON.parse(localStorage.KANJI_STATS || '');
var bar = obj[char] || {char: char, count: 0};
bar.count++;
bar.lastObserved = Date.now();
obj[char] = bar;
localStorage.KANJI_STATS = JSON.stringify(obj);
}
Kanji char | Count | Last observed
----------------------------------
char1 | 1 | 1234123412345
char2 | 2 | 4643563456345
char3 | 3 | 3245234523452
每个实例(记录)都包含一个唯一的字符。计数表示观察字符的次数。last observed属性表示最近观察角色的时间
// Setup or change the schema
function onUpgradeNeeded() {
var db = this.result;
var store = db.createObjectStore('kanji', {keyPath: kanjiChar});
store.createIndex('lastObserved','lastObserved');
}
function openDB(onOpen) {
var openRequest = indexedDB.open(DBNAME,DBVERSION);
openRequest.onupgradeneeded = onUpgradeNeeded;
openrequest.onsuccess = function() {
onOpen(this.result);
};
}
function onKeyEvent(event) {
var kanjiChar = event.target.value;
openDB(function(db) {
put(db, kanjiChar);
});
}
// Insert or update the kanji in the store
function put(db, kanjiChar, oncomplete) {
var tx = db.transaction('kanji','readwrite');
tx.oncomplete = function() {
oncomplete(kanjiChar);
};
var store = tx.objectStore('kanji');
store.openCursor(kanji).onsuccess = function() {
var cursor = this.result;
if(cursor) {
var obj = cursor.value;
obj.count = obj.count ? obj.count + 1 : 1;
obj.lastObserved = Date.now();
cursor.update(obj);
} else {
store.add({
kanjiChar: kanji,
count: 1,
lastObserved: Date.now()
});
}
};
}
function getStats(db, oncomplete) {
var tx = db.transaction('kanji');
var allStats = [];
tx.oncomplete = function() {
oncomplete(allStats);
};
var kanjiStore = tx.objectStore('kanji');
var lastObservedIndex = kanjiStore.index('lastObserved');
var LIMIT = 10;
var counter = 0;
lastObservedIndex.openCursor('prev').onsuccess = function() {
var cursor = this.result;
if(cursor) {
allStats.push(cursor.value);
if(counter++ < LIMIT) {
// Only continue
cursor.continue();
}
}
};
}
//设置或更改架构
函数onUpgradeNeeded(){
var db=此结果;
var store=db.createObjectStore('kanji',{keyPath:kanjiChar});
createIndex('lastObserved','lastObserved');
}
函数openDB(onOpen){
var openRequest=indexedDB.open(DBNAME,DBVERSION);
openRequest.onupgradeneeded=onupgradeneeded;
openrequest.onsuccess=函数(){
onOpen(this.result);
};
}
函数onKeyEvent(事件){
var kanjiChar=event.target.value;
openDB(函数(db){
put(db,kanjiChar);
});
}
//在存储中插入或更新汉字
函数put(db、kanjiChar、oncomplete){
var tx=db.transaction('kanji','readwrite');
tx.oncomplete=函数(){
未完成(kanjiChar);
};
var store=tx.objectStore('kanji');
store.openCursor(汉字).onsuccess=function(){
var cursor=this.result;
如果(光标){
var obj=cursor.value;
obj.count=obj.count?obj.count+1:1;
obj.lastObserved=Date.now();
游标更新(obj);
}否则{
store.add({
汉字,
计数:1,
lastObserved:Date.now()
});
}
};
}
函数getStats(db,oncomplete){
var tx=db.transaction(“汉字”);
var-allStats=[];
tx.oncomplete=函数(){
未完成(allStats);
};
var kanjiStore=tx.objectStore('kanji');
var lastObservedIndex=kanjiStore.index('lastObservedIndex');
var限值=10;
var计数器=0;
lastObservedIndex.openCursor('prev')。onsuccess=function(){
var cursor=this.result;
如果(光标){
allStats.push(cursor.value);
if(计数器++<极限){
//只能继续
cursor.continue();
}
}
};
}
今晚我会给你一个完整的回复,但完全有可能。同时,您可以发布您的模式和一些示例数据吗?Chrome资源面板的屏幕截图可能就足够了。@buley我不能发布屏幕截图,因为AFAIK唯一的访问方法是在扩展背景页打开开发人员工具,而且似乎有。但我会发布更多关于该模式的详细信息。@buley不介意我最后的评论。我可以通过在扩展的选项页面而不是背景页面中打开开发人员工具来截图。事实上,记录每个事件可能不是必需的,但是我想保留事件中的所有数据,以便在试用期后对其进行分析,并决定哪些最有效,哪些可以丢弃。也就是说,你的回答让我意识到,为了达到我打算使用的目的,也就是说,为了让用户知道他们最终查询的汉字是什么,以及他们应该重点研究哪个汉字,你提出的解决方案应该足够有效。谢谢你的快速回复