构建支持React Web App的SQlite / PouchDB和问题?

问题描述 投票:0回答:1

我的目标


创建一个可以通过Service Workers脱机工作的React JS WEB APP,可以在没有任何后端的情况下查询SQlite文件。我正在运行Linux操作系统。

问题


我正在努力在React Js Web应用程序上使用SQlite。我正在使用create-react-app并尝试查询SQlite数据库。

从sqlite3开始

我不能将sqlite3安装为npm包,因为它需要一个名为aws-sdk的依赖项,并且在安装此包之后,它会输出以下内容:

/node_modules/sqlite3/node_modules/node-pre-gyp/lib/util/compile.js
Module not found: Can't resolve 'npm' in '/home/user/Documents/snv3/node_modules/sqlite3/node_modules/node-pre-gyp/lib/util'

./node_modules/sqlite3/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> <!doctype html>
| <html>
| <head>

然后......我继续寻找另一个sqlite支持库,比如better-sqlite3

好SQLITE3

导入better-sqlite3时,这是我浏览器屏幕上的输出:

TypeError: Class is undefined
exports.wrap
node_modules/babel-loader/lib/index.js??ref--6-oneOf-2!/home/user/Documents/projectFolder/node_modules/better-sqlite3/lib/util.js:14

  11 | };
  12 | 
  13 | exports.wrap = function (Class, methodName, wrapper) {
> 14 |   var originalMethod = Class.prototype[methodName];
  15 | 
  16 |   if (typeof originalMethod !== 'function') {
  17 |     throw new TypeError("Missing method ".concat(methodName));

我不清楚这应该是什么意思。库的故障排除部分没有任何内容,因此无法进行调试。

Kripken的Sql.js

让我们尝试用Javascript和轻量级构建的东西。

哦不,我的内存堆爆炸试图编译它:

Starting the development server...


<--- Last few GCs --->
tart of marking 2696 ms) (average mu = 0.196, current mu = 0.078) alloca[19981:0x317f660]    30702 ms: Mark-sweep 1387.3 (1425.7) -> 1382.8 (1424.7) MB, 2779.6 / 0.0 ms  (+ 0.1 msin 91 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 2806 ms) (average mu = 0.104, current mu = 0.010) allocati[19981:0x317f660]    33503 ms: Mark-sweep 1386.7 (1424.7) -> 1385.2 (1425.7) MB, 2780.3 / 0.0 ms  (average mu = 0.056, current mu = 0.007) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x30bcb58041bd]
Security context: 0x346742d1e789 <JSObject>
    1: get [0x146f266b8549] [/home/user/Documents/projectFolder/node_modules/@babel/traverse/lib/path/index.js:~99] [pc=0x30bcb6347fd5](this=0x2c6f95aa7759 <JSFunction NodePath (sfi =0x3a532511d061)>,/* anonymous */=0xb1cce8a8af9 <Object map = 0x3450d4054639>)
    2: /* anonymous */(aka /* anonymous */) [0xb1cce8a8899] [/home/user/Documents/projectFolder/node_modul...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x8b8210 node::Abort() [/usr/local/bin/node]
 2: 0x8b825c  [/usr/local/bin/node]
 3: 0xac1d1e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 4: 0xac1f38 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 5: 0xeb11f2  [/usr/local/bin/node]
 6: 0xebd14a v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
 7: 0xebdab4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
 8: 0xec03e5 v8::internal::Heap::AllocateRawWithRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
 9: 0xe888c4 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
10: 0x112a2ae v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
11: 0x30bcb58041bd
Aborted (core dumped)

好的,忘记sqlite库,让我们试试PouchDB吧!

现行解决方案


PouchDB

所以,在所有这些混乱之后,我已经放弃了使用SQlite库并尝试脱机的第一个友好的东西:Pouch DB。我认为可以将SQlite文件加载到Pouch中。

所以我问过这个问题:What is the correct way to load prebuilt SQlite databases with or without PouchDB in a React App

不,这是一个noSQL数据库,不可能......

然后我必须将我的所有SQlite数据库转换为.json文件,手动完成所有操作...

接下来,让我们创建数据库并从.json文件中导入数据。

编辑1:

我的SQlite文件每个表都有接近5k regstries的东西。因此,我从SQlite表转换的每个.json文件都有5个k对象或文档。这些.json文件中有19个,每个文件代表一个表。

AAAAND ...我需要在.json文件(表)之间进行更改以进行查询,但在文件转换后,没有_rev属性,因此每次使用bulkDocs加载注册表时,表之间都会发生冲突,因为他们缺少_rev属性。

这是我的数据库服务的代码:

import PouchDB from 'pouchdb';
import PDBFind from 'pouchdb-find';
import PDBSilverLining from 'pouchdb-silverlining';
import TableEnumerator from '../utils/tableEnumerator';

import {
    Example_Table_Name
} from '../../db'

PouchDB.plugin(PDBFind);
PouchDB.plugin(PDBSilverLining);

class DbService {
    constructor() {
        this._db = new PouchDB('database');
    }

    static async dbLoad (table) {
        const dbInstance = new DbService()._db

        try {
            const respose = await dbInstance.bulkDocs(TableEnumerator(table))
        } catch(e) {
            console.error(e)
        }
    }

    static query(query) {
        const dbInstance = new DbService()._db

        return dbInstance.sql(query)
    }
}

export default DbService;

文档示例:

表格1:

{ "_id": "table1_010101012",
    "Procedure": "XXXXX",
    "field4": "",
    "field5": "2B",
    *insert here some more irrelevant data* }

表2:

{ "_id": "table2_0555444777",
    "Procedure": "YYYYYYYYYYY",
    "field4": "",
    "field5": "2B",
    *insert here some more irrelevant data* }

在第一个(dbLoad(Table1))调用上,将加载所有文档,并在第一个表中创建_rev属性。

当我使用Table2.json进行另一次调用(dbLoad(Table2))时,它们会发生冲突,因为新文件缺少_rev attr,当Pouch创建此属性时,它们是相同的!

编辑2:

我试图将我的代码修改为:

import PDBLoad from 'pouchdb-load';

PouchDB.plugin(PDBLoad);

static async dbLoad (table) {
        const db = new PouchDB(table);

        try {
            db.get('_local/preloaded').then(function (doc) {
            }).catch(function (err) {
              if (err.name !== 'not_found') {
                throw err;
              }
              // we got a 404, so the local docuent doesn't exist. so let's preload!
              return db.load('table_name.json').then(function () {
                // create the local document to note that we've preloaded
                return db.put({_id: '_local/preloaded'});
              });
            }).then(function () {
                console.log({include_docs: true})
              return db.allDocs({include_docs: true});
            })

        } catch(e) {
            console.error(e)
        }
    }

.json文件位于加载函数的同一目录中,但它不加载数据。

所以我坚持使用bulkDocs版本。

问题

对于很长的帖子我很抱歉,经过所有的语境化后,出现了一些问题:

  • 是否有可能在React Web App环境中设置sqlite库?
  • 没有任何后端?
  • 在我的.json表之间切换的推荐方法是什么?
  • 我应该删除之前存储的并加载下一个吗?
  • 或手动加载每个表,然后使用pouch-dump-cli转储它们?

我希望一切都得到很好的解释,我很乐意澄清你可能遇到的任何问题。

感谢您的时间!

可能的答案


好的,所以我能够通过创建这样的代码来解决我的问题。

import PouchDB from 'pouchdb';
import PDBFind from 'pouchdb-find';
import PDBSilverLining from 'pouchdb-silverlining';
import TableEnumerator from '../utils/tableEnumerator';

PouchDB.plugin(PDBFind);
PouchDB.plugin(PDBSilverLining);

class DbService {
    static async dbLoad (table) {
        const db = new PouchDB(table);

        try {
            await db.bulkDocs(TableEnumerator(table))
        } catch(e) {
            console.error(e)
        }

        return db
    }

    static async query(query, dbReference) {
        return dbReference.sql(query)
    }
}

export default DbService;

其中switch语句是表的名称并返回表docs,以便在IndexedDB上插入。对于每个.json文件,我正在创建一个新的数据库然后进行查询,因为我正在使用React,我正在为组件状态保存DB的引用。

我认为缺乏优化,因为我每次在表之间进行更改时都会调用使用bulkDocs的函数。也许我应该检查表是否已经插入到IndexedDB上。

reactjs sqlite create-react-app pouchdb better-sqlite3
1个回答
0
投票

对于未来的读者,这就是您解决问题的方法。

  1. 如果你有一个SQLite文件,请转到我之前提出的问题:What is the correct way to load prebuilt SQlite databases with or without PouchDB in a React App
  2. 搜索问题答案,并执行sqlite3命令,相应地输出.json文件。
  3. 发出SELECT命令时,如果您有任何具有特殊字符的列,如空格或其名称中的点,请使用列名[]上的方形球拍操作符: sqlite3示例“.output rslt.json”“SELECT'{\”id \“:\”someTable'|| SUBSTR(\“000000000 \”|| id,LENGTH(\“000000000 \”|| id) - 8,9)|| '\“,\”anattr \“:\”'|| anattr || '\“,\”anothe.rattr \“:\”'|| [anoth.erattr] || '\“},'FROM some_table;”;
  4. 我遇到了一个问题,一些表行有双引号:“Attr”:“Lorem ipsum”dolor“”。这会导致解析错误。为了修复它,在引号之前使用转义字符运算符\:“Lorem ipsum \”dolor \“”。这应该修复双引号。 您可以轻松地使用正则表达式来匹配这些事件:\“dolor \”,这将找到包含所需单词的双引号。为了快速替换write \“dolor \”并替换所有出现的事情,就在它之前检查你正在修改哪些文件!

由于没有人对此表现出任何意见,我在上次更新时回答了我自己的问题:

好的,所以我能够通过创建这样的代码来解决我的问题。

import PouchDB from 'pouchdb';
import PDBFind from 'pouchdb-find';
import PDBSilverLining from 'pouchdb-silverlining';
import TableEnumerator from '../utils/tableEnumerator';

PouchDB.plugin(PDBFind);
PouchDB.plugin(PDBSilverLining);

class DbService {
    static async dbLoad (table) {
        const db = new PouchDB(table);

        try {
            await db.bulkDocs(TableEnumerator(table))
        } catch(e) {
            console.error(e)
        }

        return db
    }

    static async query(query, dbReference) {
        return dbReference.sql(query)
    }
}

export default DbService;

其中switch语句是表的名称并返回表docs,以便在IndexedDB上插入。对于每个.json文件,我正在创建一个新的数据库然后进行查询,因为我正在使用React,我正在为组件状态保存DB的引用。

我认为缺乏优化,因为我每次在表之间进行更改时都会调用使用bulkDocs的函数。也许我应该检查表是否已经插入到IndexedDB上。

这会为每个.json文件创建一个DATABASE!请记住,这不是最佳的!我将为此制定一种优化方法。

谢谢,感谢Martin的帮助!

热门问题
推荐问题
最新问题