В этом уроке мы рассмотрим работу с CouchDB , базой данных NoSQL от Apache. В этом руководстве основное внимание будет уделено практической стороне, поэтому мы не будем рассказывать о том, для чего CouchDB хорош, как его устанавливать, зачем его использовать и т. Д. Мы сосредоточимся на том, как выполнять операции с базой данных через HTTP-API CouchDB и как работать с ним в PHP, закладывая основу для будущих, более сложных сообщений.
Мы предполагаем, что вы уже установили CouchDB и Futon (веб-консоль администрирования CouchDB) на своем компьютере . Если вы хотите следовать, мы рекомендуем вам использовать нашу коробку HI .
Примечание: для простоты мы будем ссылаться на нашу локальную машину с localhost
С Homestead Improved это просто вопрос перечисления портов, которые вы хотите перенаправить, в конфигурационном файле Homestead.yaml
Создание базы данных
Чтобы создать новую базу данных CouchDB, посетите Futon по адресу http://localhost:5984/_utils/
Вы увидите следующий интерфейс:
Нажмите на создание базы данных , введите имя базы данных и нажмите на создание, чтобы создать базу данных.
После создания вы увидите следующий экран:
Обратите внимание, что есть только опция для создания нового документа. В CouchDB документ является эквивалентом строки таблицы в реляционной базе данных. Итак, как мы создаем таблицы?
Если вы пришли из базы данных NoSQL, такой как MongoDB, первое, что вам нужно знать, это то, что в CouchDB нет такой вещи, как коллекции или таблицы. Есть только документы. Однако это не означает, что вы можете хранить только один тип данных для каждой базы данных. Поскольку каждый документ, который вы создаете в CouchDB, не принадлежит ни одной таблице, вы можете иметь различную структуру для каждого типа данных. Например, если вы хотите сохранить пользовательские данные, вы можете иметь структуру, подобную следующей:
{
"id": 123,
"fname": "doppo",
"lname": "kunikida",
"pw": "secret",
"hobbies": ["reading", "sleeping"]
}
С другой стороны, если вы хотите хранить информацию в блоге, вы можете иметь следующую структуру:
{
"title": "The big brown fox",
"author": "fox",
"text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum, quasi in id voluptates. Natus qui iure corporis ea voluptatem eius, possimus optio modi facere blanditiis quo, sequi suscipit eos nostrum.",
"publish_date": "2016-07-07"
}
Чтобы упростить запрос к определенному типу документа (например, пользователи, сообщения в блоге), вы можете добавить поле для хранения типа документа:
{
"id": "123",
"fname": "doppo",
"lname": "kunikida",
"pw": "secret",
"hobbies": ["reading", "sleeping"],
"type": "users"
}
Обратите внимание, что type
Это используется только для удобства.
Разговор с HTTP API
Поскольку CouchDB предоставляет HTTP API, мы также можем использовать curl
curl -X PUT http://localhost:5984/<database name>
Выполнение вышеупомянутой команды должно вернуть следующее:
{"ok":true}
CouchDB возвращает строки JSON в качестве ответа. Это делает его очень простым в использовании как в браузере, так и на стороне сервера.
Мы рекомендуем Postman для экспериментов во время этого урока, так как он позволяет легко общаться с HTTP API CouchDB. Если вы новичок в Postman, вам может помочь это введение: создание и тестирование API стало проще с Postman .
Создание новых документов
Чтобы создать новые документы, нам нужно отправить запрос POST
http://localhost:5984/test_couch
При отправке запроса в CouchDB всегда следует помнить следующее:
- Укажите
Content-Type
application/json
POST
PUT
DELETE
- Оберните строки в двойные кавычки.
Вот пример запроса для создания нового документа:
Массовая вставка
Чтобы вставить несколько строк данных в одном запросе:
Мы также будем использовать эти данные, когда поиграемся с получением документов позже. Если вы хотите следовать, вот данные для вставки: couchdb-bulk.json
Получение документов
Попробуем восстановить все документы, которые в данный момент хранятся в базе данных:
По умолчанию CouchDB возвращает только уникальный идентификатор, ключ (такой же, как уникальный идентификатор) и значение, которое по умолчанию является объектом, содержащим номер последней редакции (уникальная строка, представляющая конкретную версию документа). Мы поговорим о ревизиях позже.
Чтобы получить данные, которые мы сохранили ранее, мы должны указать include_docs
true
http://localhost:5984/test_couch/_all_docs?include_docs=true
Получение конкретных документов
В CouchDB вы можете получить определенные документы, используя идентификатор документа:
http://localhost:5984/test_couch/8939b0d23a0ba7a5ed55fd981d0010a0?include_docs=true
Вы также можете получить конкретную версию документа, указав номер редакции через параметр запроса rev
http://localhost:5984/test_couch/8939b0d23a0ba7a5ed55fd981d0010a0?rev=1-1841dec358ff29eca8c42a52f1c2a1d0&include_docs=true
Каждый раз, когда вы создаете новый документ или обновляете существующий, CouchDB генерирует уникальный номер редакции. Затем он присваивает его этому состоянию документа. Например, если вы добавите новое поле с именем skill
skill
Он делает это каждый раз, когда вы вносите изменения (например, обновляете значение для определенного поля, удаляете поле, переименовываете поле, добавляете новое поле) в документ. Это действительно полезно, если вам нужно сохранить исторические данные.
Если вы обращаетесь к конкретному документу в Futon, вы также можете перемещаться по его предыдущим версиям:
Взгляды
Представления позволяют нам извлекать конкретные данные из базы данных и упорядочивать их особым образом.
Чтобы создать представление, зайдите в базу данных на Futon и в раскрывающемся меню в правом верхнем углу выберите временное представление . Это покажет вам следующий интерфейс:
В оставшейся части урока мы будем использовать данные, которые мы вставили ранее.
Сначала давайте посмотрим на функцию, которая фильтрует Pokemon по их тренеру:
function(doc) {
emit(doc.trainer, doc.name);
}
Добавьте эту функцию в качестве значения для функции карты . Эта функция использует встроенный метод emit
Ключ — тот, который используется для фильтрации документов, а значение — это значение, которое мы хотим вернуть для каждой строки.
Вот ответ, который мы получаем, когда выполняем функцию:
Как видите, он просто возвращает все. Это потому, что мы не указали значение, которое будет использоваться в качестве фильтра. Чтобы увидеть эту функцию в действии, нам нужно сохранить вид, нажав кнопку « Сохранить как» .
Это попросит у нас название проектного документа и название вида. Вы можете думать о проектных документах как о коллекции связанных видов. Мы назовем его pokemon, поскольку документы, над которыми мы работаем, в основном касаются данных Pokemon. Что касается представления, мы назовем его в честь того, что он делает: filter_by_trainer
Теперь давайте сделаем запрос к представлению, которое мы только что создали:
http://localhost:5984/test_couch/_design/pokemon/_view/filter_by_trainer?key="Ash"
Это вернет следующие результаты:
То, что вы передадите в качестве значения параметра key
Фильтрация по полю массива
Что если нам нужно отфильтровать по полю массива, такому как поле type
Для этого нам нужно будет перебрать все элементы массива и выдать документы из цикла следующим образом:
function(doc) {
for(var x = 0; x < doc.type.length; x++){
emit(doc.type[x], doc.name);
}
}
Сохраните это представление как filter_by_type
GET
http://localhost:5984/test_couch/_design/pokemon/_view/filter_by_type?key="Fire"
Это вернет всех покемонов с «Огнем» как один из их типов:
Сортировка и ограничение результатов
Чтобы отсортировать результаты, все, что вам нужно сделать, это выделить поле, с которым вы хотите отсортировать. В этом случае мы будем использовать owned
function(doc){
emit(doc.owned, doc.name);
}
Сохраните это представление как order_by_owned
http://localhost:5984/test_couch/_design/pokemon/_view/sort_by_owned
По умолчанию CouchDB возвращает документы в порядке возрастания, поэтому первыми идут те покемоны, которым принадлежал самый длинный. Чтобы отсортировать документы в порядке убывания, укажите в качестве параметра запроса descending=true
http://localhost:5984/test_couch/_design/pokemon/_view/sort_by_owned?descending=true
Чтобы ограничить количество возвращаемых документов, установите limit
http://localhost:5984/test_couch/_design/pokemon/_view/sort_by_owned?limit=5
Группировка результатов
Если вы хотите вернуть количество покемонов, которое есть у каждого уникального тренера, нам нужно использовать функцию уменьшения. Функция Reduce позволяет нам выполнять операции группировки и агрегирования результатов, возвращаемых функцией map. CouchDB поставляется с тремя встроенными функциями сокращения: _count
_sum
_stats
Мы рассмотрим _count
_count
Мы можем использовать функцию function(doc) {
Начните с добавления следующей функции карты:
emit(doc.trainer, doc.name);
}
_count
Для функции сокращения group_by_trainer
Затем сохраните вид с именем http://localhost:5984/test_couch/_design/pokemon/_view/group_by_trainer?group=true
Сделайте запрос на следующий URL:
group=true
Установка {
"rows": [
{
"key": null,
"value": 9
}
]
}
group=true
Приведенный выше результат показывает только общее количество документов, которые в данный момент находятся в базе данных. Это означает, что функция сокращения считала весь набор результатов, возвращаемый функцией карты, одной группой.
Установка doc.trainer
{
"rows": [
{
"key": "Ash",
"value": 5
},
{
"key": "Brock",
"value": 1
},
{
"key": "Misty",
"value": 2
},
{
"key": "Team Rocket",
"value": 1
}
]
}
PUT
Обновление документов
Чтобы обновить документы, мы отправляем запрос DELETE
На основе приведенного выше снимка экрана видно, что CouchDB не поддерживает обновление определенных полей: вам нужно извлечь существующие данные, выполнить обновления и затем отправить обновленные данные обратно в базу данных.
Удаление документов
Чтобы удалить документ, выполните запрос http://localhost:5984/test_couch/<Document ID>?rev=<Revision ID>
GET
Он имеет тот же формат, что и URL-адрес для извлечения документа, и поскольку мы передаем идентификатор редакции, это означает, что мы можем также удалить определенные редакции документа (отменить функцию кого-либо?).
Работа с PHP
Есть два способа работы с CouchDB в PHP. Первый — через Guzzle , а другой — через библиотеку, специально созданную для работы с CouchDB, например, CouchDB Client от Doctrine. В этом разделе мы рассмотрим, как работать с каждой из этих библиотек.
пропивать
При получении данных мы должны использовать запрос query
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new GuzzleHttp\Client([‘base_uri’ => ‘http://localhost:5984’]);
$response = $client—>request(‘GET’, ‘/test_couch/_all_docs’, [
‘query’ => [
‘include_docs’ => ‘true’
]
]);
$json = $response—>getBody()—>getContents();
$data = json_decode($json, true);
$docs = [
'docs' => [
[
"name" => "Tangela",
"type" => ["Grass"],
"trainer" => "Erika",
"gender" => "f",
"owned" => "1999-07-27"
],
[
"name" => "Wobbuffet",
"type" => ["Psychic"],
"trainer" => "Elesa",
"gender" => "m",
"owned" => "2014-09-09"
],
[
"name" => "Gogoat",
"type" => ["Grass"],
"trainer" => "Ramos",
"gender" => "m",
"owned" => "2015-10-17"
]
]
];
$client->request('POST', '/test_couch/_bulk_docs', [
'headers' => [
'Content-Type' => 'application/json'
],
'body' => json_encode($docs)
]);
Далее давайте сделаем массовую вставку:
PUT
Из приведенного выше кода видно, что применяются те же правила.
Чтобы обновить документ, используйте запрос body
А затем передайте измененный документ в $doc = [
'_rev' => '2-ff235602e45c46aed0f8834c32817546',
'name' => 'Blastoise',
'type' => ['Water'],
'gender' => 'm',
'trainer' => 'Ash',
'owned' => '1999-05-21'
];
$client—>request(‘PUT’, ‘/test_couch/5a6a50b7c98499a4d8d69d4bfc00029a’, [
‘headers’ => [
‘Content-Type’ => ‘application/json’
],
‘body’ => json_encode($doc)
]);
DELETE
Чтобы удалить документ, используйте запрос query
$client->request('DELETE', '/test_couch/7c7f800ee10a39f512a456339e0019f3', [
'query' => [
'rev' => '1-967a00dff5e02add41819138abb3284d'
]
]);
CouchDBClient
Doctrine CouchDB Client
Далее давайте посмотрим, как работать с базой данных CouchDB с клиентом CouchDB .
Сначала мы должны создать новый экземпляр <?php
require 'vendor/autoload.php';
$client = \Doctrine\CouchDB\CouchDBClient::create([‘dbname’ => ‘test_couch’]);
$client->postDocument([
"name" => "Lucario",
"type" => ["Fighting", "Steel"],
"trainer" => "Korrina",
"gender" => "f",
"owned" => "2015-02-13"
]);
Затем мы передаем документ, который мы хотим создать в виде массива. За кулисами это будет преобразовано в строку JSON, которая принимается CouchDB.
createViewQuery
Чтобы получить документы с использованием определенного представления, мы передаем имя проектного документа и имя представления в качестве аргументов функции setKey
Затем мы можем установить ключ с помощью метода execute
Чтобы получить ответ, мы вызываем метод $query = $client->createViewQuery('pokemon', 'filter_by_trainer');
$query->setKey('Ash');
$result = $query->execute();
echo "Pokemon trained by Ash: <br>";
foreach($result as $row){
echo $row['value'] . "<br>";
}
Pokemon trained by Ash:
Blastoise
Pikachu
Charizard
Talonflame
Froakie
Это даст следующий результат:
setGroup
Если вы добавили функцию сокращения в представление, вы должны вызвать метод true
setGroup
Установка true
trainer
$query = $client->createViewQuery('pokemon', 'group_by_trainer');
$query->setReduce('true');
$query->setGroup('true');
$result = $query->execute();
foreach($result as $row){
echo $row['key'] . "<br>";
echo "Pokemon count: " . $row['value'] . "<br>";
echo "<br>";
}
Это даст нам следующий результат:
Ash
Pokemon count: 5
Brock
Pokemon count: 1
Elesa
Pokemon count: 1
Erika
Pokemon count: 1
Korrina
Pokemon count: 1
Misty
Pokemon count: 3
Ramos
Pokemon count: 1
Team Rocket
Pokemon count: 1
Чтобы обновить документ, сначала мы должны найти его самую последнюю версию. Это связано с тем, что клиент CouchDB не предоставляет функциональности, которая позволяет нам просто передавать поля, которые мы хотим обновить. CouchDB — это база данных только для добавления, поэтому нам всегда нужно получить текущую версию документа, обновить или добавить нужные нам поля, а затем выполнить фактическое обновление.
$doc_id = '5a6a50b7c98499a4d8d69d4bfc003c9c';
$doc = $client->findDocument($doc_id);
$updated_doc = $doc->body;
$updated_doc['name'] = 'Golduck';
$updated_doc['owned'] = '1999-07-29';
$client->putDocument($updated_doc, $doc->body['_id'], $doc->body['_rev']);
Как и при обновлении документа, нам нужно выполнить запрос GET
Затем мы вызываем функцию deleteDocument
$doc_id = '7c7f800ee10a39f512a456339e0027fe';
$doc = $client->findDocument($doc_id);
$client->deleteDocument($doc_id, $doc->body['_rev']);
Вывод
CouchDB — это очень удобная и простая в использовании база данных документов с акцентом на производительность и контроль версий.
Теперь вы научились работать с ним и выполнять различные операции с базой данных с помощью Postman и двух клиентов PHP. Если вы хотите узнать больше, я рекомендую вам ознакомиться с Подробным руководством, которое содержит все, что вам нужно знать о CouchDB. В следующем посте мы пойдем гораздо глубже и создадим правильное мультиплатформенное приложение, используя все, что мы видели до сих пор.
До тех пор, как их лозунг говорит — расслабься!