Disclaimer
This article does not encourage you to give up everything you are used to and switch to using Couchbase without regard to all your past experience and the shoals that you have encountered while developing your own projects. This article is intended to be only a brief description of the use of Couchbase Server in conjunction with PHP and only. Perhaps it will be interesting to some as a description of opportunities, and perhaps also as an evaluative look at perspectives.
What is it and what does it eat
Couchbase is another NoSQL database line developed by Couchbase, Inc., and is a direct heir to the traditions and problems of its parent CouchDB. This is a document-oriented database, which implies storing each individual record as a document, although this is not a hard and fast rule, and any value can be used as a record (up to BLOB rows), but the beauty of this (and other databases too) is document-oriented data storage method.
The document-oriented data storage method implies that all data will be stored in the form of so-called documents, i.e. sets of fields combined into a document based on the principles of common sense and common logic present in the record. An example of such an entry could be, for example, a user profile, a list of fields such as: login, password, email, and others. The standard for storing documents in this case is the document format in the form of a JSON string. This format was chosen by the creators consciously, as it is quite popular, easily interpretable and human-readable. But it does not matter. It is important that you have an idea of ​​what a document is and how it looks inside the database.
Required components for work
To work with Couchbase using PHP, we need several software items:
')
After successful installation of all this stuff and successful launch, we have the opportunity to use a class called Couchbase, which is described in the
official Couchbase Git repository . For convenience of future use, I advise you to add it to yourself in the project, so that your favorite IDe successfully earns autocomplete.
In addition, for convenient operation, you will need to create a separate Bucket (analogue of the database) in the couchbase itself, due to which you will not have to foul in the common and standard default. This is done by calling on the address
localhost : 8091 / index.html # sec = buckets and clicking on the button "Create new bucket".
Begin to code
Coding something abstract does not make sense, so let's take a very specific example given above, namely the user profile. Suppose our user has several fields: login, password, email, and from implicit one - this is his integer type identifier. In the JSON view, the received document will look like this:
{ "login": "megausername", "password": "my secured password!", "email": "email@example.com" }
First we need to know how this file can be saved to the database and how it can be obtained from there. This is done quite simply, and can be clearly seen in the following example:
<?php $couchbase = new Couchbase(array('localhost'), 'couchbase_user', 'couchbase_password', 'users_bucket', TRUE); $document = array( 'login' => 'megausername', 'password' => 'my secured password!', 'email' => 'email@example.com' ); $userId = $couchbase->increment('counter::users', 1, TRUE); try { $couchbase->add("profile::{$userId}", json_encode($document)); } catch(\CouchbaseException $e)
As you can see, in the above example, there is absolutely no difficulty, except for the generation of the user ID. Difficulties will begin immediately after you need to start searching.
What is View and how to work with it
If you go to the Couchbase server control panel, you will notice there is one wonderful thing called Views. It will have two sub-items “Development views” and “Production views”. It’s not hard to guess the mapping (and in the Couchbase section this is a sample). While there it is empty, but we will understand how to spoil there.
View is essentially indexes, the rules for creating which can be described in JavaScript. Yes Yes. Indices here are created on the basis of the logic described by you and carry not just an enumerated function, but also some semantic one. For example, the index can include users whose email is longer than n characters, or only certain fields are present. To work with indexes, we only have JavaScript, but it is more than enough. The index is updated either on demand (when requesting data), or automatically, when database fragmentation reaches a certain percentage (specified in the Bucket settings). This point also needs to be considered when developing.
You can create a view in two ways. The first of these is to write JavaScript rules directly in the control panel in the Development section and transfer them to Production, or directly from PHP, pull the setDesignDoc method with a description of the scripts that will directly fall into the Production section.
First, consider the script and what it should consist of. The script is a function, at the entrance to which is a description of the meta information of the document and its contents. Let's consider the creation of an index, based on the user's login.
function (doc, meta) {
Thanks to the above-described JavaScript method, it can be understood that the index (which is generated using the emit method) will only contain entries that have a login field. As you can see, the JavaScript function is designed as a callback function that will be applied to each entry located in this Bucket. It should be noted that the view can be created at any time the existence of the bucket life cycle. Those. If you need to add new functionality, you can easily add new views and continue to live as you like.
So. Let us understand how we can find out the user ID, if we only know his login. To do this, we need to create a new index (we will create it immediately from the PHP code) and call it.
$designedDocument = array( 'language' => 'javascript', 'views' =>array( 'login' => array( 'map' => 'function (doc, meta) {if (meta.type == "json" && doc.login) {var userid = meta.id.split("::"); emit(doc.login, parseInt(userid[1]));}}' ) ), ); $couchbase->setDesignDoc('userFields', json_encode($designedDocument));
If immediately after the execution of this code, we go into the Couchbase control panel, we will see (on large volumes) in the upper right index creation progress. Upon completion of which, you can check its work by opening it in the control panel and clicking on the "Show Results" button. In the answer we will see key / value pairs that were generated by the javascript callback method.
From the PHP code we can get a sample by the following request:
The response will have an array of two elements: total_rows - where the total number of records for the given index will be contained and the rows field - in which there will be an array of arrays from our selection in the form: array ('id' => 'profile :: 0', 'key '=>' megausername ',' value '=> 0). In this array of fields: _id is the identifier of the document that was selected. Key is the key that was specified when forming the index, and value is the value that we formed.
But it is necessary to take into account the fact that in this way we will get the whole index, which is not quite suitable for us to search. And if we need to find only the identifier? Do not go through the whole index manually. Of course not. And for this, with each request to the view, you can specify additional parameters. For example, if we want to know only the identifier of the user specified by login, then we must specify a specific key in the request for the view. This is done like this:
$result = $couchbase->view('userFields', "login", array('key'=>'megausername'));
And this is a happy moment when, as a result, we will only have a record, the key of which is equal to 'megausername'. With which we can work and be happy. Here are just one pitfall. As mentioned above, the index is not rebuilt at the moment of adding or changing the record to the specified Bucket, but only when a certain percentage of Bucket fragmentation is reached.
Suppose we have a need to check for the uniqueness of the username before performing any operation. For example, when registering a user. Naturally, we will execute a query to this view and will analyze the response of the database. However, there is a possibility that at the same moment a user with the same name has just registered, and the index has not yet managed to rebuild. Naturally, we will receive information that there is no such record in the index and we will get some collision. In order to avoid such a situation, it is possible, when calling the view index, to indicate to it the need to rebuild the index. Those. all operations that were not performed on this index will be completed first, and then the query will be executed and the result will be returned. This is done by adding the stale option with the value FALSE. This is done like this:
$result = $couchbase->view('userFields', "login", array('key'=>'megausername', 'stale'=>FALSE));
As a result of this query, all operations on the index will be completed and you will get a real result, which is in the database. It is important to take this moment into account when dealing with such specific data.
Conclusion
As you can see, working with Couchbase Server is not so difficult, it is important to thoroughly examine the documentation before starting work and not forget to think and analyze your actions. I will not agitate everyone to switch to Couchbase, but I would like to say that for me personally, the ability to work with the database without drastically changing the structure when adding new fields was a very “tasty” factor in developing the system described above. However, the harsh reality returns everything to its place. In my particular case, there was a question about the formation of statistics for individual fields in real time, and interaction with the system of storing / analyzing statistics running on the MSSQL engine. This fact led to the organization of "crutches" for the convenient work of our DBA developers, which resulted in the fact that the field management system was duplicated in SQL format. If you want to use NoSQL database engines in your projects, then I advise you to start with standalone projects that are not tied to the internal infrastructure, because integrate painlessly you will not succeed.
If you have any questions, I advise you to study the documentation, which is located at
www.couchbase.com/documentationIf you continue to be interested in this topic, then it can be opened at a somewhat more difficult level. Consider the methodology of migration from SQL thinking to NoSQL, documented in the following articles. Consider how to organize GROUP BY, ORDER and other interesting things using Couchbase, as well as to consider more deeply questions on the optimization and design of document-oriented databases.