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