1

我的目标


创建一个 React JS WEB APP,它可以通过Service Workers离线工作,并且可以在没有任何后端的情况下查询 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

Better-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。

所以我问了这个问题:在 React App 中加载带有或不带有 PouchDB 的预构建 SQlite 数据库的正确方法是什么

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

然后我不得不将我所有的 SQlite 数据库转换为 .json 文件,这一切都是手动完成的......

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

编辑1:

我的 SQlite 文件每张表有接近 5k 的注册表。因此,我从 SQlite 表转换的每个 .json 文件都有 5 k 个对象或文档,如您所愿。其中有 19 个 .json 文件,每个代表一个表。

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 属性,并且当 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 表之间切换的推荐方式是什么?
  • 我应该删除存储的前一个并加载下一个吗?
  • 或手动加载每个表,然后使用袋转储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 语句是表的名称并返回表文档,用于在 IndexedDB 上插入。对于每个 .json 文件,我正在创建一个新的数据库,然后进行查询,因为我正在使用 React,我正在将数据库的引用保存在组件状态上。

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

4

1 回答 1

2

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

  1. 如果您有 SQLite 文件,请转到我之前提出的问题:在 React 应用程序中加载预构建的 SQlite 数据库(无论是否使用 PouchDB)的正确方法是什么
  2. 搜索问题答案,然后执行 sqlite3 命令相应地输出 .json 文件。

  3. 发出命令 SELECT 时,如果您有任何包含特殊字符的列,例如其名称中的空格或点,请在列名称 [ ] 上使用方形球拍运算符:

    sqlite3 示例 ".output rslt.json" "SELECT '{ \" id\": \"someTable ' || SUBSTR(\"000000000\" || id, LENGTH(\"000000000\" || id) - 8, 9) || '\", \"anattr\": \"' || 分析 || '\", \"anthe.rattr\": \"' || [另一个.erattr] || '\" },' FROM some_table;";

  4. 我遇到了一个问题,一些表格行有这样的双引号:“Attr”:“Lorem ipsum “dolor” “。这会导致解析错误。为了修复它,请在引号之前使用转义字符运算符 \:“Lorem ipsum \"dolor\"”。那应该修复双引号。

    您可以轻松地使用正则表达式来匹配此事件:\"dolor\",这将在其中找到带有所需单词的双引号。要快速替换,请写入\"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 语句是表的名称并返回表文档,用于在 IndexedDB 上插入。对于每个 .json 文件,我正在创建一个新的数据库,然后进行查询,因为我正在使用 React,我正在将数据库的引用保存在组件状态上。

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

这会为每个 .json 文件创建一个数据库!!!请记住,这不是最佳选择!我将为此研究一种优化的方法。

感谢并感谢马丁的帮助!

于 2019-03-03T19:18:39.823 回答