一直在探索使用pouch db,以便我们可以利用其离线同步而不是自己做。我们有一个cordova应用程序,它从REST API中提取数据并将其保存到Web sql存储中。其中一部分是各种商店的约5k个物理位置。我在cordova应用程序上计时,我们下载商店&在大约11秒内保存它们以及另一个项目信息请求。只需将这些5k记录保存为包db中的文档需要30秒。不计算请求时间。
这就是我的所作所为:
let db = PouchProxy.getDB();
this.render("loading", { message: "Saving locations" });
// stores from api
let stores = res.stores;
let docs = [];
// check for saved stores, checking ids that start with store_
db.allDocs({ include_docs: true, startkey: 'store_', endkey: 'store_\uffff' }).then((results) => {
// go through saved stores
for (let row of results.rows) {
let doc = row.doc;
// get the number id. The _id is simply 'store_idnumfromapi'
let id = parseFloat(doc._id.split('store_')[1]);
if (isNaN(id)) {
throw "Cannot be NaN";
}
// iterate through stores from api
for (var i = 0; i < stores.length; i++) {
let store = stores[i];
// find store and local record
if (store.id === id) {
// sets the _id and other properties from the store api object to a new object
let map = PouchProxy.storeToDocMap(store);
// set revision
map._rev = doc._rev;
docs.push(map);
stores.splice(i, 1);
break;
}
}
}
// go through remaining stores and push to docs set
for (let store of stores) {
docs.push(PouchProxy.storeToDocMap(store));
}
// save all the things
console.log(Date.now());
return db.bulkDocs(docs);
}).then(() => {
// this the second time stamp i use to get the 30 seconds
console.log(Date.now());
// calculate geolocation stuff
for (let store of docs) {
store.distance = this.distanceBetweenPoints(store, { lat: position.coords.latitude, long: position.coords.longitude });
}
docs.sort((a, b) => {
return b.distance - a.distance;
});
this.render("store-list", { stores: docs.slice(0, 19) });
}).catch(function (err) {
console.log(err);
});
希望代码足够清晰。我考虑过为商店切换到一个文档,但后来我觉得单个查找会更加困难和昂贵。
编辑,修改代码。表现实际上更糟:(
根据建议,我将5000列表分成了块。我玩了几个不同的尺寸。 300&amp; 500,两者的保存数据非常相似。以下是它现在的样子:
saveLocations(db, stores) { // position
var storeSlices = [];
stores.sort(function (a, b) {
return a.id - b.id;
});
stores.eachSlice(300, (slice) => {
storeSlices.push(slice);
});
console.log(Date.now());
this.commitBatch(db, storeSlices, 0, () => {
console.log(Date.now());
// this.sortAndRenderStores(docs, position);
this.render("store-list", { stores: [] });
});
}
commitBatch(db, slices, index, callback) {
let stores = slices[index];
db.allDocs({ include_docs: true, startkey: 'store_' + stores[0].id, endkey: 'store_' + stores[stores.length - 1].id }).then((results) => {
let docs = [];
for (let row of results.rows) {
let doc = row.doc;
let id = parseFloat(doc._id.split('store_')[1]);
if (isNaN(id)) {
throw "Cannot be NaN";
}
// iterate through stores from api
for (var i = 0; i < stores.length; i++) {
let store = stores[i];
// find store and local record
if (store.id === id) {
let map = PouchProxy.storeToDocMap(store);
// set revision
map._rev = doc._rev;
docs.push(map);
stores.splice(i, 1);
break;
}
}
}
// go through remaining stores and push to docs set
for (let store of stores) {
docs.push(PouchProxy.storeToDocMap(store));
}
db.bulkDocs(docs).then(() => {
index++;
if (index < slices.length) {
this.commitBatch(db, slices, index, callback);
}
else {
callback();
}
});
}).catch(function (err) {
console.log(err);
});
}
答案 0 :(得分:3)
我的猜测是,这里的问题是你要一次性将所有文档读入内存(或至少每个文档都以store_
为前缀,这是allDocs()
正在做的事情),然后你也会一次性写出所有这些文件。
5000个文件很多。我对PouchDB的体验是bulkDocs()
有一个最佳位置(取决于你的文档大小),它可能小于5000.这适用于IndexedDB和WebSQL。
您最有可能通过批量处理100-500块来加速代码,同时使用allDocs()
和limit
在startkey
中进行分页(即使用{{3}中描述的策略}}),然后使用bulkDocs()
一次插入100-500。
作为我没有反复的证据,您可以查看this blog post,它会在一个bulkDocs()
中每批次从npm插入大约500个元数据文档,并且绝对不会每批需要7秒。 (花费的大部分时间都在网络上等待下载文件。)