Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 266 lines (224 sloc) 9.944 kb
dc718b5 @kallaspriit Added example file explaining the core features of the library.
authored
1 Cassandra PHP-based client library for managing and querying your Cassandra
2 cluster. It's a high-level library performing all the rather complex low-level
3 lifting and providing a simple to learn and use interface.
4
5 Features:
6 - simple and intuitive interface
7 - well covered with unit tests (>90%)
8 - support for multiple server pools using named singletons
9 - requires including a single file
10 - uses reasonable defaults through-out
11 - powerful syntax for querying data
12 - enables managing keyspaces and column-families
13 - automatic packing of datatypes using column metadata
14 - retries failed queries using back-off strategy
15 - built with performance in mind (caches schema description etc)
16 - well documented API and a working example
17
18
19 The following example covers most of what you need to know to use this library.
20 It should work out-of-box on a machine with default cassandra setup running. The
21 example file is contained in the download.
22
23 <?php
24
25 // the only file that needs including into your project
26 require_once 'Cassandra.php';
27
28 // list of seed servers to randomly connect to
29 // all the parameters are optional and default to given values
30 $servers = array(
31 array(
32 'host' => '127.0.0.1',
33 'port' => 9160,
34 'use-framed-transport' => true,
35 'send-timeout-ms' => 1000,
36 'receive-timeout-ms' => 1000
37 )
38 );
39
40 // create a named singleton, the second parameter name defaults to "main"
41 // you can have several named singletons with different server pools
42 $cassandra = Cassandra::createInstance($servers);
43
44 // at any point in code, you can get the named singleton instance, the name
45 // again defaults to "main" so no need to define it if using single instance
46 $cassandra2 = Cassandra::getInstance();
47
48 // drop the example keyspace and ignore errors should it not exist
49 try {
50 $cassandra->dropKeyspace('CassandraExample');
51 } catch (Exception $e) {}
52
53
54 // create a new keyspace, accepts extra parameters for replication options
55 // normally you don't do it every time
56 $cassandra->createKeyspace('CassandraExample');
57
58 // start using the created keyspace
59 $cassandra->useKeyspace('CassandraExample');
60
61 // if a request fails, it will be retried for this many times, each time backing
62 // down for a bit longer period to prevent floods; defaults to 5
63 $cassandra->setMaxCallRetries(5);
64
65 // create a standard column family with given column metadata
66 $cassandra->createStandardColumnFamily(
67 'CassandraExample', // keyspace name
68 'user', // the column-family name
69 array( // list of columns with metadata
70 array(
71 'name' => 'name',
72 'type' => Cassandra::TYPE_UTF8,
73 'index-type' => Cassandra::INDEX_KEYS, // create secondary index
74 'index-name' => 'NameIdx'
75 ),
76 array(
77 'name' => 'email',
78 'type' => Cassandra::TYPE_UTF8
79 ),
80 array(
81 'name' => 'age',
82 'type' => Cassandra::TYPE_INTEGER,
83 'index-type' => Cassandra::INDEX_KEYS,
84 'index-name' => 'AgeIdx'
85 )
86 )
87 // actually accepts more parameters with reasonable defaults
88 );
89
90 // create a super column family
91 $cassandra->createSuperColumnFamily(
92 'CassandraExample',
93 'cities',
94 array(
95 array(
96 'name' => 'population',
97 'type' => Cassandra::TYPE_INTEGER
98 ),
99 array(
100 'name' => 'comment',
101 'type' => Cassandra::TYPE_UTF8
102 )
103 ),
104 // see the definition for these additional optional parameters
105 Cassandra::TYPE_UTF8,
106 Cassandra::TYPE_UTF8,
107 Cassandra::TYPE_UTF8,
108 'Capitals supercolumn test',
109 1000,
110 1000,
111 0.5
112 );
113
114 // lets fetch and display the schema of created keyspace
115 $schema = $cassandra->getKeyspaceSchema('CassandraExample');
116 echo 'Schema: <pre>'.print_r($schema, true).'</pre><hr/>';
117
118 // should we need to, we can access the low-level client directly
119 $version = $cassandra->getConnection()->getClient()->describe_version();
120 echo 'Version directly: <pre>'.print_r($version, true).'</pre><hr/>';
121
122 // if implemented, use the wrapped methods as these are smarter - can retry etc
123 $version = $cassandra->getVersion();
124 echo 'Version through wrapper: <pre>'.print_r($version, true).'</pre><hr/>';
125
126 // cluster is a pool of connections
127 $cluster = $cassandra->getCluster();
128 echo 'Cluster: <pre>'.print_r($cluster, true).'</pre><hr/>';
129
130 // you can ask the cluster for a connection to a random seed server from pool
131 $connection = $cluster->getConnection();
132 echo 'Connection: <pre>'.print_r($connection, true).'</pre><hr/>';
133
134 // access column family, using the singleton syntax
135 // there is shorter "cf" methid that is an alias to "columnFamily"
136 $userColumnFamily = Cassandra::getInstance()->columnFamily('user');
137 echo 'Column family "user": <pre>'.print_r($userColumnFamily, true).'</pre><hr/>';
138
139 // lets insert some test data using the convinience method "set" of Cassandra
140 // the syntax is COLUMN_FAMILY_NAME.KEY_NAME
141 $cassandra->set(
142 'user.john',
143 array(
144 'email' => 'john@smith.com',
145 'name' => 'John Smith',
146 'age' => 34
147 )
148 );
149
150 // when inserting data, it's ok if key name contains ".", no need to escape them
151 $cassandra->set(
152 'user.jane.doe',
153 array(
154 'email' => 'jane@doe.com',
155 'name' => 'Jane Doe',
156 'age' => 24
157 )
158 );
159
160 // longer way of inserting data, first getting the column family
161 $cassandra->cf('user')->set(
162 'chuck', // key name
163 array( // column names and values
164 'email' => 'chuck@norris.com',
165 'name' => 'Chuck Norris',
166 'age' => 24
167 ),
168 Cassandra::CONSISTENCY_QUORUM // optional consistency to use
169 // also accepts optional custom timestamp and time to live
170 );
171
172 // lets fetch all the information about user john
173 $john = $cassandra->get('user.john');
174 echo 'User "john": <pre>'.print_r($john, true).'</pre><hr/>';
175
176 // since the jane key "jane.doe" includes a ".", we have to escape it
177 $jane = $cassandra->get('user.'.Cassandra::escape('jane.doe'));
178 echo 'User "jane.doe": <pre>'.print_r($jane, true).'</pre><hr/>';
179
180 // there is some syntatic sugar on the query of Cassandra::get() allowing you
181 // to fetch specific columns, ranges of them, limit amount etc. for example,
182 // lets only fetch columns name and age
183 $chuck = $cassandra->get('user.chuck:name,age');
184 echo 'User "chuck", name and age: <pre>'.print_r($chuck, true).'</pre><hr/>';
185
186 // fetch all solumns from age to name (gets all columns in-between too)
187 $chuck2 = $cassandra->get('user.chuck:age-name');
188 echo 'User "chuck", columns ago to name: <pre>'.print_r($chuck2, true).'</pre><hr/>';
189
190 // the range columns do not need to exist, we can get character ranges
191 $chuck3 = $cassandra->get('user.chuck:a-z');
192 echo 'User "chuck", columns a-z: <pre>'.print_r($chuck3, true).'</pre><hr/>';
193
194 // when performing range queries, we can also limit the number of columns
195 // returned (2); also the method accepts consistency level as second parameter
196 $chuck4 = $cassandra->get('user.chuck:a-z|2', Cassandra::CONSISTENCY_ALL);
197 echo 'User "chuck", columns a-z, limited to 2 columns: <pre>'.print_r($chuck4, true).'</pre><hr/>';
198
199 // the Cassandra::get() is a convinience method proxying to lower level
200 // CassandraColumnFamily::get(), no need to worry about escaping with this.
201 // column family has additional methods getAll(), getColumns(), getColumnRange()
202 // that all map to lower level get() calls with more appopriate parameters
203 $jane2 = $cassandra->cf('user')->get('jane.doe');
204 echo 'User "jane.doe", lower level api: <pre>'.print_r($jane2, true).'</pre><hr/>';
205
206 // we defined a secondary index on "age" column of "user" column family so we
207 // can use CassandraColumnFamily::getWhere() to fetch users of specific age.
208 // this returns an iterator that you can go over with foreach or use the
209 // getAll() method that fetches all the data and returns an array
210 $aged24 = $cassandra->cf('user')->getWhere(array('age' => 24));
211 echo 'Users at age 24: <pre>'.print_r($aged24->getAll(), true).'</pre><hr/>';
212
213 // if we know we are going to need to values of several keys, we can request
214 // them in a single query for better performance
215 $chuckAndJohn = $cassandra->cf('user')->getMultiple(array('chuck', 'john'));
216 echo 'Users "chuck" and "john": <pre>'.print_r($chuckAndJohn, true).'</pre><hr/>';
217
218 // we can fetch a range of keys but this is predictable only if using an
219 // order preserving partitioner, Cassandra defaults to random one
220 // again as there may be more results than it's reasonable to fetch in a single
221 // query, an iterator is returned that can make several smaller range queries
222 // as the data is iterated
223 $usersAZ = $cassandra->cf('user')->getRange('a', 'z');
224 echo 'Users with keys in range a-z: <pre>'.print_r($usersAZ->getAll(), true).'</pre><hr/>';
225
226 // find the number of columns a key has, we could also request for ranges
227 $chuckColumnCount = $cassandra->cf('user')->getColumnCount('chuck');
228 echo 'User "chuck" column count: <pre>'.print_r($chuckColumnCount, true).'</pre><hr/>';
229
230 // we can find column counts for several keys at once
231 $chuckJaneColumnCounts = $cassandra->cf('user')->getColumnCounts(array('chuck', 'jane.doe'));
232 echo 'User "chuck" and "jane.doe" column counts: <pre>'.print_r($chuckJaneColumnCounts, true).'</pre><hr/>';
233
234 // setting supercolumn values is similar to normal column families
235 $cassandra->set(
236 'cities.Estonia',
237 array(
238 'Tallinn' => array(
239 'population' => '411980',
240 'comment' => 'Capital of Estonia',
241 'size' => 'big'
242 ),
243 'Tartu' => array(
244 'population' => '98589',
245 'comment' => 'City of good thoughts',
246 'size' => 'medium'
247 )
248 )
249 );
250
251 // fetch all columns of Tartu in Estonia of cities
252 $tartu = $cassandra->cf('cities')->getAll('Estonia', 'Tartu');
253 echo 'Super-column cities.Estonia.Tartu: <pre>'.print_r($tartu, true).'</pre><hr/>';
254
255 // we could also use the higher level Cassandra::get() to fetch supercolumn info
256 // we can still use the additional filters of columns
257 $tallinn = $cassandra->get('cities.Estonia.Tallinn:population,size');
258 echo 'Super-column cities.Estonia.Tallinn: <pre>'.print_r($tallinn, true).'</pre><hr/>';
259
260 // you can delete all the data in a column family using "truncate"
261 $cassandra->truncate('user');
262
263 // you may choose to drop an entire keyspace
264 $cassandra->dropKeyspace('CassandraExample');
265
266 ?>
Something went wrong with that request. Please try again.