GunDB: графическая база данных на JavaScript

Тойота.png

Часть 1: Основы оружия

Первоначально опубликовано на Середина

Недавно я играл с GunDB и я хотел поделиться с вами тем, что я узнал до сих пор. GunDB, также известный как Gun, также известный как Gun.js, — это больше, чем просто база данных графов. Это группа проектов, направленных на упрощение масштабирования, повышение безопасности данных, снижение затрат и расширение возможностей разработчиков приложений.

Однако в этой статье я буду рассматривать Gun исключительно как базу данных. Сосредоточившись только на аспекте базы данных, я могу сделать статью менее перегруженной и исследовать другие аспекты в следующих статьях по мере того, как я продвигаюсь вперед и узнаю больше.

Все примеры кода для этой статьи доступны на Гитлаб

Введение

Вообще говоря, база данных — это часть программного обеспечения, которое вы устанавливаете на свой компьютер или на удаленный сервер для хранения данных. Данные могут храниться как на диске, так и в памяти. Базы данных бывают разных видов: реляционные, ориентированные на документы, ключ-значение или основанные на графах. Вот некоторые примеры:

  • Реляционные: MySql, PostgreSQL, SQL Server.
  • Документоориентированные: MongoDB, CouchDB
  • Ключ-значение: Redis, LevelDB
  • На основе графа: Neo4j, OrientDB

Gun, в отличие от других баз данных, не требует установки бинарного файла. Пистолет написан на JavaScript, что означает, что вы можете использовать его везде, где работает JavaScript. Начать работу с Gun так же просто, как загрузить файл JavaScrip.

Начиная

Самый простой способ начать работу с Gun — загрузить его в виде одного файла JavaScript. Вы можете загрузить последнюю уменьшенную версию по следующему адресу:


Затем вы можете загрузить его в HTML-файл:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="gun.min.js"></script> 
  <title>Gun Basics</title>
</head>
<body>
</body>
</html>

Затем вы можете открыть HTML-файл в браузере и использовать консоль для взаимодействия с Gun. В большинстве браузеров вы можете щелкнуть правой кнопкой мыши на странице и выбрать «Проверить элемент», чтобы открыть консоль. Ниже приведен пример, который вы можете использовать для создания записи автомобиля и печати его марки:

const db = window.Gun();
const car = db.get("123").put({
  make: "Toyota",
  model: "Camry",
});
car.once(v => console.log(v.make)); 

В приведенном выше фрагменте мы сначала создаем экземпляр Gun. Затем мы ссылаемся на пустой узел, используя get метод с 123 ключ. Затем мы добавляем некоторые данные, используя put метод и простой объект JavaScript. И, наконец, мы используем тот же ключ, чтобы получить запись (узел) и, используя once методом мы считываем значение. Обратите внимание, что простой объект автоматически преобразуется в узел Gun. Я объясню каждый метод более подробно позже в разделе «Основы». Ниже приведена диграмма, которая поможет вам лучше понять, что происходит:


Создание записи карты

Теперь давайте поэкспериментируем с Gun, используя Node. Сначала создайте каталог и установите Gun, используя npm:

Если у вас не установлены Node и npm, инструкции можно найти в Приложении 1.

cd ~/Desktop && mkdir gun-demo && cd $_
npm init -y
npm i gun -S

Затем создайте файл и назовите его main.js и добавьте следующее (очень похоже на приведенное выше):

main.js

const db = require('gun')();
const car = db.get("123").put({
  make: "Toyota",
  model: "Camry",
});
car.once(v => console.log(v.make)); 

Затем выполните файл с помощью node main и вы должны быть в состоянии видеть Toyota залогинился в консоли. Кроме того, вы можете использовать Gun в Node’s REPL, сначала вызвав node в терминале, а затем выполните следующее:

const db = require('gun')();

Затем вы можете взаимодействовать с Gun, используя db объект. Чтобы закрыть REPL, используйте ctrl + c дважды.

Основы оружия

В следующих разделах я собираюсь показать вам основы Gun и изучить его основные методы создания, чтения, обновления и удаления записей. Я также покажу вам, как создавать наборы и отношения. Я также кратко упомяну о различных способах, доступных для подписки на обновления записей. Обратите внимание, что я буду использовать термины «запись» и «узел» взаимозаменяемо, поскольку Gun — это графовая база данных, а записи представлены в виде узлов.

CRUD

Для создания записи можно использовать get метод в сочетании с put:

const entry = db.get('8899').put({
  uuid: '8899',
  some_prop: 'some value',
});

В приведенном выше фрагменте мы используем get метод для создания ссылки на узел с помощью 8899 ключ. Затем мы используем put для добавления данных в узел с помощью простого объекта JavaScript. Простой объект автоматически преобразуется в узел Gun. Обратите внимание, что если данный ключ уже существует, добавленные данные могут переопределить существующие данные. Более подробно я расскажу об обновлениях в разделе «Обновление». На приведенной ниже диаграмме показано, как данный ключ в базе данных указывает на узел:


Создание узла

Небольшое примечание о ключах: вы всегда должны использовать уникальные ключи. Вы можете использовать uuid для общих узлов и хешированные строки в сочетании с читаемыми строками для целей индексации. Пространство имен очень важно при работе с Gun, потому что все данные существуют в глобальном пространстве. Вы можете посмотреть на это расширение чтобы помочь вам создать пространство имен для ваших ключей.

Мы можем использовать get метод поиска узла по ключу. Затем мы можем подписаться на него, используя on или же once. С использованием on вы можете получать обновления по мере их появления, но once выдает текущее значение только один раз:

const node = db.get("1122").once(v => console.log(v));

Вы можете продолжать цепочку get звонки. Если ссылки не существуют, они создаются. В противном случае возвращается значение по указанному пути. Давайте посмотрим на пример. Ниже мы создаем узел с именем node1 с некоторыми свойствами:

const node1 = db.get("3344").put({
  name: "node1"
});
node1.get("doc1").put({
  name: "doc1",
});
node1.get("doc1").get("sub_doc").put({
  name: 'sub_doc',
});

Например, чтобы получить доступ к значению node1.doc1.sub_doc мы можем использовать get цепочку и прочитайте значение, используя once:

node1.get('doc1').get('sub_doc').once(v => console.log(v));

На приведенной ниже диаграмме показано, как выглядят узлы и отношения:


Связь между тремя узлами

Несколько замечаний по поводу приведенных выше фрагментов:

  • Когда вы используете put, если ключ не указан явно, ключ (также известный как душа) генерируется автоматически. В дополнение db объект также сохранит ссылку на этот ключ. Например, когда мы сделали node1.get("doc1").put, за кулисами был сгенерирован новый узел с уникальным ключом. Мы можем видеть, что если мы зарегистрируем значение node1.doc1 и посмотри на внутр. _ имущество:


Внутреннее значение, показывающее автоматически сгенерированный ключ

Теперь, если вы знаете этот уникальный ключ (душу) узла, вы можете напрямую получить доступ к узлу, на который он указывает, из db объект:

db.get('unique_key')...
  • То же самое верно и для node1.doc1.sub_doc:


Внутреннее значение, показывающее автоматически сгенерированный ключ

  • Также обратите внимание, что node1.doc1 имеет свойство, называемое sub_doc который содержит только ссылку на sub_doc узел:


Сохранение ссылки на другой узел

Учитывая приведенные выше пояснения, ниже представлена ​​более точная картина узлов и их взаимосвязей:


Узлы и отношения

Обратите внимание, как два других автоматически сгенерированных уникальных ключа (души) указывают на вновь созданные узлы непосредственно из db.

Чтобы обновить запись, вы можете использовать put метод:

db.get('9871').put({ name: 'Tom',});

Обратите внимание, что все обновления являются частичными обновлениями. В приведенном выше фрагменте обновляется только поле имени. Пока у вас есть ссылка на узел, вы можете просто использовать put для обновления значений. Давайте посмотрим на другой пример. Ниже приведена настройка:

const n1 = db.get('5416')
  .put({
    name: 'n1',
    prop: '...',
    doc1: {
      prop: '...',
    },
  });

const n2 = db.get('8899')
  .put({
    name: 'n2',
    doc2: {
      prop: '...',
    }
  });

n1.get('related_to').put(n2);

В приведенном выше фрагменте мы создаем два узла: n1 а также n2. n1 узел имеет некоторые свойства name, propа также doc1. doc1 Свойство определяет вложенный документ, который автоматически превращается в узел и на который ссылается автоматически сгенерированный ключ.

Затем мы создаем n2 узел, который имеет два свойства nameа также doc2 похожий на n1. И, наконец, мы создаем свойство на n1 называется related_to это указывает на n2. На приведенной ниже диаграмме показаны отношения:


Настройка отношений для демонстрации обновлений

Теперь давайте посмотрим, как мы можем выполнить следующие обновления:

  • Обновлять n1.doc1.prop к другому значению:
n1.get('doc1').put({ prop: 'other value'});
  • Обновить что n1 относится к
n1.get('related_to').put(db.get('9185').put({ new_prop: 'some value', }));

В приведенном выше фрагменте мы полностью меняем то, что n1 указывает, создавая новый узел. Обратите внимание, что n2 ничего не изменилось, мы просто обновили related_to указатель.

  • Добавьте новые свойства в n2сначала ссылаясь на n1:
n1.get('related_to').put({
  new_stuff: 'some value',
  other_stuff: 'some value',
})

Во фрагменте выше new_stuff а также other_stuff будет добавлено к тому, что уже существует на n2. Если свойство уже существует, оно будет перезаписано, в противном случае будут созданы новые свойства.

Удаление работает немного по-другому в Gun. Вместо удаления записи мы можем сделать ее невозможной для обнаружения, установив указатель на null:

db.get('8809').put(null);

В приведенном выше фрагменте мы используем get найти ссылку на 8809 ключ. Затем мы устанавливаем его на null. Пока у вас есть ссылка на узел или свойство, вы можете использовать put установить их на null. Подробнее об удалении можно прочитать по следующим ссылкам:

Вот краткое объяснение, взятое непосредственно из ответа StackOverflow:

Удаление в GUN работает как Mac OSX, Windows или Linux. Обнуление говорит каждой машине «Поместить эти данные в корзину». Причина, по которой это полезно, заключается в том, что это позволяет вам изменить свое мнение об удалении чего-либо, чтобы вы могли восстановить его позже, если хотите. (Восстановление удаленного контента/файлов происходит МНОГО, но большинство людей об этом не задумываются).

Наборы

Gun позволяет группировать несколько записей и добавлять их в набор. Набор оружия — это математический набор с уникальными неупорядоченными элементами. Допустим, у нас есть два узла, и мы хотим создать для них группу. Сначала мы создаем узел группы, а затем используем set чтобы добавить к нему другие узлы или простые объекты. Обратите внимание, что простые объекты, как и операции обновления, будут автоматически преобразованы в узлы Gun:

const group = db.get('8871'); // create a group node
group.set(n1);
group.set(n2);

В настоящее время group имеет две записи, n1 а также n2. Вы также можете добавить в набор простые объекты:

const group = db.get('8871');
group.set({
  title: 'hello'
});
group.set({
  title: 'world'
});

В этом случае Gun автоматически создаст узлы из простых объектов. На диаграмме ниже показан набор и узлы, на которые он указывает:


Визуализация набора с двумя записями

Отношения

Моделирование реального мира сводится к выявлению взаимосвязей и реализации их в базе данных. Базы данных графов, естественно, хороши для выражения отношений. В этом разделе я собираюсь показать вам, как создавать отношения между узлами.

Самый простой способ создания отношения, как мы уже видели, — это использование следующего шаблона:

node1.get('related_to').put(node2)

или явное создание отношения при создании узла:

const node1 = db.get('8891').put({
  uuid: '8891',
  name: 'node1',
  related_to: {
    uuid: '9911',
    name: 'node2',
  },
});

Во фрагменте выше related_to автоматически превращается в узел Gun, а ссылка сохраняется в node1. Затем вы можете получить доступ к связанному узлу с помощью node.get('related_to').

Теперь, если вы хотите добавить свойства отношения, вы можете создать промежуточный узел и добавить свойства отношения и ссылку внутри промежуточного узла:

node1.get('related_to').put({
  property: "value",
  property2: "value",
});
node1.get('related_to').get('node').put(node2);

На приведенной ниже диаграмме показаны отношения:


Создание отношения с помощью узла свойства

Как вы можете видеть на диаграмме выше, related_to узел указывает на node2 сквозь node свойство промежуточного узла. Затем вы можете получить доступ node2 с node1.get('relate_to').get('node').

Подписка

Узлы Gun являются наблюдаемыми, что означает, что они излучают значения с течением времени. Вы можете подписаться на узлы Gun, используя on или же once. С использованием on вы можете получать обновления по мере их появления, если только вы не отмените подписку. once метод извлекает только текущее значение и не подписывается на будущие обновления.

Итерация по записям

Учитывая набор записей, вы можете перебирать их, используя map:

myset.map().once(v => console.log(v));

Приведенный выше фрагмент будет регистрировать каждую запись в myset однажды. Он также будет добавлять записи с течением времени, но только один раз.

Вот еще шаблоны, которые можно использовать (взять прямо из документации):

  • myset.map().on(cb): подписывается на изменения каждой записи и на myset по мере добавления новых записей в будущем.
  • myset.map().once(cb): получает каждую запись один раз, включая те, которые добавляются с течением времени.
  • myset.once().map().on(cb): получает список записей один раз, но подписывается на изменения в каждой из них. mysetа не добавленные позже записи.
  • myset.once().map().once(cb): получает список записей один раз, получает каждую запись в myset только один раз, а не добавленные позже.

Вывод

GunDB меняет наше представление о базах данных и постепенно переводит нас к новой парадигме. Gun и связанные с ним проекты имеют множество аспектов, сильно отличающихся от классических централизованных моделей. Вы можете столкнуться с трудностями в изучении оружия, если вы только начинаете. Во-первых, потому что Gun — молодой проект, и вы должны ожидать изменения API. А во-вторых, вам может быть сложно разобраться в документации.

Я надеюсь, что эта серия статей поможет вам (и мне) лучше понять GunDB и послужит дополнительным руководством к ранее существовавшим руководствам. Вы можете получить доступ ко всей официальной документации и руководствам на

Приложение 1

Самый простой и наиболее последовательный способ установки Node — через диспетчер версий, например NVM. Сначала установите NVM, используя следующее:

curl -o-  | bash

Затем проверьте свой файл «профиль», чтобы увидеть, были ли добавлены следующие записи:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  

Затем перезапустите терминал и убедитесь, что вы можете получить вывод для nvm --version. После этого просто запустите nvm install 8 для установки последней версии Node 8. После этого запустите node -v а также npm -v чтобы убедиться, что и Node, и Npm доступны.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *