PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/mongoxx/query.hh

http://github.com/saalweachter/MongoXX
C++ Header | 201 lines | 161 code | 36 blank | 4 comment | 10 complexity | 3925f26e083ffb762d7e46ba8ea4155d MD5 | raw file
Possible License(s): MIT
  1. /* query.hh
  2. Queries!
  3. */
  4. #ifndef MONGOXX_QUERY_HH
  5. #define MONGOXX_QUERY_HH
  6. #include "mapper.hh"
  7. #include "session.hh"
  8. #include "filter.hh"
  9. #include "update.hh"
  10. #include <string>
  11. #include <stdexcept>
  12. #include <tr1/memory>
  13. namespace mongoxx {
  14. class Session;
  15. class query_error : public std::runtime_error {
  16. public:
  17. explicit query_error(std::string const &message) : runtime_error(message) { }
  18. };
  19. template <typename T>
  20. class QueryResult {
  21. public:
  22. QueryResult(std::tr1::shared_ptr<mongo::DBClientCursor> const& cursor, Mapper<T> const* mapper)
  23. : m_cursor(cursor), m_mapper(mapper) { }
  24. T first() const {
  25. if (m_cursor->more()) {
  26. mongo::BSONObj obj = m_cursor->next();
  27. return m_mapper->from_bson(obj);
  28. }
  29. throw query_error("Query returned no results; cannot return the first element.");
  30. }
  31. T one() const { return first(); }
  32. bool next(T &t) const {
  33. if (m_cursor->more()) {
  34. mongo::BSONObj obj = m_cursor->next();
  35. m_mapper->from_bson(obj, t);
  36. return true;
  37. }
  38. return false;
  39. }
  40. bool first(T &t) const {
  41. return next(t);
  42. }
  43. bool one(T &t) const {
  44. return next(t);
  45. }
  46. bool more() const {
  47. return m_cursor->more();
  48. }
  49. T next() const {
  50. if (m_cursor->more()) {
  51. mongo::BSONObj obj = m_cursor->next();
  52. return m_mapper->from_bson(obj);
  53. }
  54. throw query_error("Query results are empty; cannot return any more results.");
  55. }
  56. std::vector<T> all() const {
  57. std::vector<T> res;
  58. for (T t; next(t); res.push_back(t));
  59. return res;
  60. }
  61. private:
  62. std::tr1::shared_ptr<mongo::DBClientCursor> m_cursor;
  63. Mapper<T> const* m_mapper;
  64. };
  65. template <typename T>
  66. class Query {
  67. public:
  68. Query(Session *session, std::string const& collection, Mapper<T> const* mapper)
  69. : m_session(session), m_collection(collection), m_mapper(mapper),
  70. m_limit(0), m_skip(0), m_sort_direction(0) { }
  71. QueryResult<T> result() const {
  72. return m_session->execute_query(m_collection, query(), m_limit, m_skip,
  73. m_mapper);
  74. }
  75. T first() const {
  76. return limit(1).result().first();
  77. }
  78. T one() const {
  79. return limit(1).result().one();
  80. }
  81. std::vector<T> all() const {
  82. return result().all();
  83. }
  84. void remove_all() const {
  85. m_session->remove_all(m_collection, query());
  86. }
  87. void remove_one() const {
  88. m_session->remove_one(m_collection, query());
  89. }
  90. Query filter(Filter const& by) const {
  91. return Query(m_session, m_collection, m_mapper,
  92. (m_filters, by), m_limit, m_skip,
  93. m_sort_by, m_sort_direction);
  94. }
  95. void update(Update const& update) const {
  96. return m_session->execute_update(m_collection, m_filters.to_bson(), update.to_bson());
  97. }
  98. void update(T const& t) const {
  99. return update(Update("$set", remove_id(m_mapper->to_bson(t))));
  100. }
  101. Query skip(unsigned int N) const {
  102. return Query(m_session, m_collection, m_mapper, m_filters, m_limit, N,
  103. m_sort_by, m_sort_direction);
  104. }
  105. Query limit(unsigned int N) const {
  106. return Query(m_session, m_collection, m_mapper, m_filters, N, m_skip,
  107. m_sort_by, m_sort_direction);
  108. }
  109. template <typename U>
  110. Query ascending(U T::*field) const {
  111. return Query(m_session, m_collection, m_mapper, m_filters, m_limit,
  112. m_skip, m_mapper->lookup_field(field), 1);
  113. }
  114. template <typename U>
  115. Query descending(U T::*field) const {
  116. return Query(m_session, m_collection, m_mapper, m_filters, m_limit,
  117. m_skip, m_mapper->lookup_field(field), -1);
  118. }
  119. template <typename U>
  120. Query ascending(U (T::*getter)()) const {
  121. return Query(m_session, m_collection, m_mapper, m_filters, m_limit,
  122. m_skip, m_mapper->lookup_field(getter), 1);
  123. }
  124. template <typename U>
  125. Query descending(U (T::*getter)()) const {
  126. return Query(m_session, m_collection, m_mapper, m_filters, m_limit,
  127. m_skip, m_mapper->lookup_field(getter), -1);
  128. }
  129. private:
  130. Query(Session *session, std::string const& collection, Mapper<T> const* mapper,
  131. Filter const& filters, unsigned int limit, unsigned int skip,
  132. std::string sort_by, int sort_direction)
  133. : m_session(session), m_collection(collection), m_mapper(mapper),
  134. m_filters(filters), m_limit(limit), m_skip(skip),
  135. m_sort_by(sort_by), m_sort_direction(sort_direction) { }
  136. Session *m_session;
  137. std::string m_collection;
  138. Mapper<T> const* m_mapper;
  139. Filter m_filters;
  140. unsigned int m_limit;
  141. unsigned int m_skip;
  142. std::string m_sort_by;
  143. int m_sort_direction;
  144. mongo::Query query() const {
  145. mongo::Query query(m_filters.to_bson());
  146. if (m_sort_direction != 0) {
  147. query.sort(m_sort_by, m_sort_direction);
  148. }
  149. return query;
  150. }
  151. mongo::BSONObj remove_id(mongo::BSONObj const& base) const {
  152. mongo::BSONObjBuilder builder;
  153. mongo::BSONObj filter = m_filters.to_bson();
  154. std::set<std::string> fields;
  155. base.getFieldNames(fields);
  156. for (std::set<std::string>::const_iterator i = fields.begin(); i != fields.end(); ++i) {
  157. if (*i == "_id") continue;
  158. builder.append(base[*i]);
  159. }
  160. return builder.obj();
  161. }
  162. };
  163. };
  164. #endif