/ARedisSortedSet.php

https://github.com/phpnode/YiiRedis · PHP · 230 lines · 128 code · 16 blank · 86 comment · 19 complexity · 2ad99f87f6e1931a1f1e7a69bffdb92f MD5 · raw file

  1. <?php
  2. /**
  3. * Represents a redis sorted set.
  4. *
  5. * Redis Sorted Sets are, similarly to Redis Sets, non repeating collections of Strings. The difference is that every member of a Sorted Set is associated with score, that is used in order to take the sorted set ordered, from the smallest to the greatest score. While members are unique, scores may be repeated.
  6. *
  7. * <pre>
  8. * $set = new ARedisSortedSet("mySortedSet");
  9. * $set->add("myThing", 0.5);
  10. * $set->add("myOtherThing", 0.6);
  11. *
  12. * foreach($set as $key => $score) {
  13. * echo $key.":".$score."\n";
  14. * }
  15. * </pre>
  16. *
  17. * @author Charles Pick
  18. * @package packages.redis
  19. */
  20. class ARedisSortedSet extends ARedisIterableEntity {
  21. /**
  22. * Adds an item to the set
  23. * @param string $key the key to add
  24. * @param integer $value the score for this key
  25. * @return boolean true if the item was added, otherwise false
  26. */
  27. public function add($key, $value) {
  28. if (!$this->getConnection()->getClient()->zadd($this->name,$value, $key)) {
  29. return false;
  30. }
  31. $this->_data = null;
  32. $this->_count = null;
  33. return true;
  34. }
  35. /**
  36. * Removes an item from the set
  37. * @param string $key the item to remove
  38. * @return boolean true if the item was removed, otherwise false
  39. */
  40. public function remove($key) {
  41. if (!$this->getConnection()->getClient()->zrem($this->name,$key)) {
  42. return false;
  43. }
  44. $this->_data = null;
  45. $this->_count = null;
  46. return true;
  47. }
  48. /**
  49. * Increment (or decrement if $byAmount is negative) the score of an item from the set
  50. * @param integer $byAmount the amount to increment by, defaults to 1
  51. * @return integer the new value of the score if was incremented, otherwise false
  52. */
  53. public function increment($key, $byAmount = 1)
  54. {
  55. if (!($score = $this->getConnection()->getClient()->zincrby($this->name, $byAmount, $key))) {
  56. return false;
  57. }
  58. $this->_data = null;
  59. $this->_count = null;
  60. return $score;
  61. }
  62. /**
  63. * Gets the intersection between this set and the given set(s), stores it in a new set and returns it
  64. * @param ARedisSortedSet|string $destination the destination to store the result in
  65. * @param mixed $set The sets to compare to, either ARedisSortedSet instances or their names
  66. * @param array $weights the weights for the sets, if any
  67. * @return ARedisSortedSet a set that contains the intersection between this set and the given sets
  68. */
  69. public function interStore($destination, $set, $weights = null) {
  70. if ($destination instanceof ARedisSortedSet) {
  71. $destination->_count = null;
  72. $destination->_data = null;
  73. }
  74. else {
  75. $destination = new ARedisSortedSet($destination,$this->getConnection());
  76. }
  77. if (is_array($set)) {
  78. $sets = $set;
  79. }
  80. else {
  81. $sets = array($set);
  82. }
  83. foreach($sets as $n => $set) {
  84. if ($set instanceof ARedisSortedSet) {
  85. $sets[$n] = $set->name;
  86. }
  87. }
  88. array_unshift($sets,$this->name);
  89. $parameters = array(
  90. $destination->name,
  91. $sets,
  92. );
  93. if ($weights !== null) {
  94. $parameters[] = $weights;
  95. }
  96. $total = call_user_func_array(array(
  97. $this->getConnection()->getClient(),
  98. "zinter"
  99. ),$parameters);
  100. $destination->_count = $total;
  101. return $destination;
  102. }
  103. /**
  104. * Gets the union of this set and the given set(s), stores it in a new set and returns it
  105. * @param ARedisSortedSet|string $destination the destination to store the result in
  106. * @param mixed $set The sets to compare to, either ARedisSortedSet instances or their names
  107. * @param array $weights the weights for the sets, if any
  108. * @return ARedisSortedSet a set that contains the union of this set and the given sets
  109. */
  110. public function unionStore($destination, $set, $weights = null) {
  111. if ($destination instanceof ARedisSortedSet) {
  112. $destination->_count = null;
  113. $destination->_data = null;
  114. }
  115. else {
  116. $destination = new ARedisSortedSet($destination,$this->getConnection());
  117. }
  118. if (is_array($set)) {
  119. $sets = $set;
  120. }
  121. else {
  122. $sets = array($set);
  123. }
  124. foreach($sets as $n => $set) {
  125. if ($set instanceof ARedisSortedSet) {
  126. $sets[$n] = $set->name;
  127. }
  128. }
  129. array_unshift($sets,$this->name);
  130. $parameters = array(
  131. $destination->name,
  132. $sets,
  133. );
  134. if ($weights !== null) {
  135. $parameters[] = $weights;
  136. }
  137. $total = call_user_func_array(array(
  138. $this->getConnection()->getClient(),
  139. "zunion"
  140. ),$parameters);
  141. $destination->_count = $total;
  142. return $destination;
  143. }
  144. /**
  145. * Returns an iterator for traversing the items in the set.
  146. * This method is required by the interface IteratorAggregate.
  147. * @return Iterator an iterator for traversing the items in the set.
  148. */
  149. public function getIterator()
  150. {
  151. return new CMapIterator($this->getData());
  152. }
  153. /**
  154. * Gets the number of items in the set
  155. * @return integer the number of items in the set
  156. */
  157. public function getCount() {
  158. if ($this->_count === null) {
  159. $this->_count = $this->getConnection()->getClient()->zcard($this->name);
  160. }
  161. return $this->_count;
  162. }
  163. /**
  164. * Gets all the members in the sorted set
  165. * @param boolean $forceRefresh whether to force a refresh or not
  166. * @return array the members in the set
  167. */
  168. public function getData($forceRefresh = false) {
  169. if ($forceRefresh || $this->_data === null) {
  170. $this->_data = $this->getConnection()->getClient()->zrange($this->name,0, -1, true);
  171. }
  172. return $this->_data;
  173. }
  174. /**
  175. * Returns whether there is an item at the specified offset.
  176. * This method is required by the interface ArrayAccess.
  177. * @param integer $offset the offset to check on
  178. * @return boolean
  179. */
  180. public function offsetExists($offset)
  181. {
  182. return ($offset>=0 && $offset<$this->getCount());
  183. }
  184. /**
  185. * Returns the item at the specified offset.
  186. * This method is required by the interface ArrayAccess.
  187. * @param integer $offset the offset to retrieve item.
  188. * @return mixed the item at the offset
  189. * @throws CException if the offset is invalid
  190. */
  191. public function offsetGet($offset)
  192. {
  193. return $this->_data[$offset];
  194. }
  195. /**
  196. * Sets the item at the specified offset.
  197. * This method is required by the interface ArrayAccess.
  198. * @param integer $offset the offset to set item
  199. * @param mixed $item the item value
  200. */
  201. public function offsetSet($offset,$item)
  202. {
  203. $this->add($offset,$item);
  204. }
  205. /**
  206. * Unsets the item at the specified offset.
  207. * This method is required by the interface ArrayAccess.
  208. * @param integer $offset the offset to unset item
  209. */
  210. public function offsetUnset($offset)
  211. {
  212. $this->remove($offset);
  213. }
  214. }