Создайте React JS ВЕБ-ПРИЛОЖЕНИЕ, который может работать в автономном режиме через Сервисные работники и может запрашивать файл SQlite без какого-либо бэкэнда. Я использую ОС Linux.
Я борюсь с использованием SQlite в веб-приложении React Js. Я использую создать-реагировать-приложение и пытаюсь запросить базу данных SQlite.
Я не могу установить 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, такой как лучше-sqlite3.
Когда лучше-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));
Я понятия не имею, что это должно означать. В разделе библиотеки для устранения неполадок ничего нет, поэтому отладка невозможна.
Давайте попробуем что-нибудь построенное на 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!
Итак, после всего этого беспорядка я отказался от использования библиотек SQlite и попытался сделать что-то, что было в первую очередь удобно в автономном режиме: Pouch DB. Я думал, что можно загрузить файл SQlite в Pouch.
Итак, я задал этот вопрос: Как правильно загружать готовые базы данных SQlite с PouchDB или без него в приложении React
Нет, это база данных noSQL, это невозможно...
Затем мне пришлось преобразовать всю мою базу данных SQlite в файлы .json, я сделал все это вручную...
Далее давайте создадим базу данных и импортируем данные из файлов .json.
Редактировать 1:
В моем файле SQlite есть что-то близкое к 5k реестров в каждой таблице. Таким образом, каждый файл .json, который я преобразовал из таблицы SQlite, содержит 5 тыс. объектов или документов по вашему усмотрению. И таких файлов .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.
Когда я делаю другой вызов (dbLoad(Table2)), используя Table2.json, они конфликтуют, потому что в новом файле отсутствует атрибут _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.info({include_docs: true})
return db.allDocs({include_docs: true});
})
} catch(e) {
console.error(e)
}
}
Файл .json находился в том же каталоге, что и функция загрузки, но он не загружает данные.
Так что я придерживаюсь версии bulkDocs.
Прошу прощения за очень длинный пост, и после всей контекстуализации возникают вопросы:
Я надеюсь, что все хорошо объяснено, и я буду рад прояснить любые вопросы, которые могут у вас возникнуть.
Спасибо за уделенное время!
Итак, я смог решить свою проблему, создав такой код.
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. Как я упоминал в другом вопросе, во второй части сообщения блога Готовые базы данных с PouchDB есть пример того, как быстро инициализировать PouchDB из файлов JSON. До вашего недавнего обновления вы, кажется, говорили, что успешно использовали это. Вы?
Ах да, я забыл упомянуть, что когда вы пытаетесь загрузить файлы с помощью pouchdb-load, он запускает команду JSON.parse, которая ожидает, что ваш JSON является строкой, иначе она терпит неудачу, несмотря на то, что она является допустимой. JSON так нежизнеспособен?
Это ошибка, которую выдает JSON.parse: SyntaxError: «JSON.parse: неожиданный символ в строке 1, столбце 2 данных JSON», мне потребовалось некоторое время, чтобы понять, что это ошибка для типа JSON. Вы можете проверить это здесь: developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
извините, теперь неясно, решили ли вы свою предыдущую проблему с pouchdb-load, или вы знаете, что это такое, но не можете ее решить. Кроме того, решение проблемы pouchdb-load решит весь вопрос, или вы все еще хотите создавать свои собственные объемные документы?
Мне пришлось создать класс DbService, потому что pouchdb-load не может анализировать простой файл .json, он должен быть НИТЬ, иначе он не будет работать. Вот почему я использую bulkDocs, это единственный способ импортировать файлы в хранилище IndexedDB. Проблема в том, что если я выдаю команду для импорта другого файла, они конфликтуют, и мне нужно переключаться между файлами, чтобы пользователь мог запрашивать другие таблицы, которые хранятся в этих файлах.
Но в этом примере ожидается, что db.load('turtles.txt') извлечет файл с исходного сервера. Конечно, «SyntaxError: «JSON.parse: неожиданный символ в строке 1, столбце 2 данных JSON»» означает, что «turtles.txt» не найден.
Да, поэтому я изменил свой код, чтобы он выполнял _db.load('table_name.json'), и он находится в той же папке, но вызывает ошибку JSON.parse, поэтому я не знаю, что делать.
Не могли бы вы посмотреть, что произойдет, если вы измените имя на что-то вроде _db.load('causeError.json', просто чтобы проверить, действительно ли он загружает файл. Кроме того, что произойдет, если вы проверите файл в JSON красивая печать?
JSON действителен, но, похоже, нет возможности загрузить файлы, так как для загрузки используется JSON.parse, а его содержимое должно быть строкой.
Итак, по сути db.load() как описано в части 2 "Загрузка из файла дампа" статьи Готовые базы данных с PouchDB в корне сломан и работать больше не будет?
Я не уверен в этом, на самом деле это не работает для моей проблемы, потому что он не может загрузить простой файл .json, а только его строковое представление.
У меня есть подозрение, что основной причиной ваших трудностей все время были двойные кавычки в столбцах varchar. Стоит проверить это, а не предполагать, что pouchdb-load «... не удается загрузить простой файл .json ...»





Для будущих читателей, вот как вы можете решить проблему.
Найдите ответ на вопрос и выполните команды sqlite3 соответственно, выводя файлы .json.
При вводе команды SELECT, если у вас есть какие-либо столбцы со специальными символами, такими как пробел или точки в имени, используйте оператор квадратных ракеток в имени столбца [ ]:
пример sqlite3 ".output rslt.json" "SELECT '{ \"идентификатор \": \"некотораяТаблица' || SUBSTR(\"000000000\" || id, LENGTH(\"000000000\" || id) - 8, 9) || '\", \"анаттр\": \"' || анаттр || '\", \"anothe.rattr\": \"' || [anoth.erattr] || '\" },' FROM some_table;";
У меня возникла проблема, в некоторых строках таблицы были такие двойные кавычки: "Attr": "Lorem ipsum "долор"". Это вызывает ошибку синтаксического анализа. Для исправления используйте оператор управляющего символа \ перед кавычками: "Lorem ipsum \"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!!! Помните, это не оптимально! Я буду работать над оптимизированным подходом для этого.
Спасибо и спасибо Мартин за вашу помощь!
Вы можете убедиться, что ваш запрос на миграцию данных Sqlite последовательно экспортирует чистый чистый JSON с помощью строковой функции Sqlite REPLACE() Таким образом, вместо '\", \"anothe.rattr\": \"' || [anoth.erattr] || '\" у вас будет '\", \"anothe.rattr\": \"' || REPLACE([anoth.erattr], '"', '\"' || '\". (Отказ от ответственности: не проверено! Возможно, вам удалось избежать некоторых кавычек и, возможно, даже избежать экранирования.)
Вы делаете два противоречащих друг другу утверждения: «Тогда я, наконец, смог импортировать данные .json в Pouch! Какое облегчение!», но затем вы заявляете: «Далее давайте создадим базу данных и импортируем данные из файлов .json». Ваши примеры кода, кажется, пытаются достичь последнего, но я не могу понять, зачем вам вообще нужен этот код, если вы «... наконец-то смогли импортировать данные .json в Pouch!»