/src/test/scala/couch/db/ViewServerWithObjectsSpec.scala

http://scouchdb.googlecode.com/ · Scala · 271 lines · 208 code · 52 blank · 11 comment · 0 complexity · 0e5f691fbb814f23f4add93ad4ff99bf MD5 · raw file

  1. package couch.db
  2. import org.scalatest.Spec
  3. import org.scalatest.BeforeAndAfter
  4. import org.scalatest.FeatureSuite
  5. import org.scalatest.matchers.ShouldMatchers
  6. import couch.json._
  7. class ViewServerWithObjectsSpec extends Spec with ShouldMatchers with BeforeAndAfter {
  8. val couch = Couch("127.0.0.1")
  9. val carDb = Db("car_inventory_db")
  10. override def beforeAll {
  11. try {
  12. couch(carDb.delete)
  13. }
  14. catch {
  15. case _ =>
  16. }
  17. couch(carDb.create)
  18. println(couch(carDb as_str))
  19. // assert(status == 201)
  20. println("** created database")
  21. }
  22. override def afterAll {
  23. couch(carDb.delete)
  24. // assert(status == 200)
  25. println("** destroyed database")
  26. }
  27. describe("create records") {
  28. it("should create new records") {
  29. def newCar(carId : String) = Doc(carDb, carId)
  30. // add
  31. couch(newCar("honda_civic_new_red") add CarSaleItem("Honda", "Civic", 16000, "New", "Red"))
  32. couch(newCar("tesla_roadster_new_orange") add CarSaleItem("Tesla", "Roadster", 90000, "New", "Orange"))
  33. couch(newCar("bmw_mini_used_redwhiteblue") add CarSaleItem("BMW", "Mini", 12500, "Used", "Red/White/Blue"))
  34. couch(newCar("ford_mustang_used_silver") add CarSaleItem("Ford", "Mustang", 14500, "Used", "Silver"))
  35. couch(newCar("geo_metro_used_red") add CarSaleItem("Geo", "Metro", 7500, "Used", "Red"))
  36. }
  37. }
  38. describe("Create, query, view : only maps") {
  39. it("should identify red cars") {
  40. // query by id to get back the object
  41. // returns a tuple3 of (id, rev, object)
  42. val (id, rev, item) = couch(carDb by_id("bmw_mini_used_redwhiteblue", classOf[CarSaleItem]))
  43. id should equal("bmw_mini_used_redwhiteblue")
  44. item.make should equal("BMW")
  45. item.model should equal("Mini")
  46. // map function
  47. val redCarsPrice =
  48. """(doc: dispatch.json.JsValue) => {
  49. val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
  50. if (car.color.contains("Red")) List(List(car.make, car.price)) else Nil
  51. }"""
  52. // map function
  53. val redCars =
  54. """(doc: dispatch.json.JsValue) => {
  55. val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
  56. if (car.color.contains("Red")) List(List(car.make, car)) else Nil
  57. }"""
  58. val redCarsView = new View(redCars, null)
  59. val redCarsPriceView = new View(redCarsPrice, null)
  60. val cv = DesignDocument("car_views", null, Map[String, View]())
  61. cv.language = "scala"
  62. val rcv = DesignDocument(cv._id, null, Map("red_cars" -> redCarsView, "red_cars_price" -> redCarsPriceView))
  63. rcv.language = "scala"
  64. couch(Doc(carDb, rcv._id) add rcv)
  65. val ls1 = couch(carDb view(
  66. Views builder("car_views/red_cars") build))
  67. println(ls1)
  68. ls1.size should equal(3)
  69. val ls2 = couch(carDb view(
  70. Views builder("car_views/red_cars_price") build))
  71. println(ls2)
  72. ls2.size should equal(3)
  73. }
  74. }
  75. describe("View results fetched as JSON and converted to objects after return") {
  76. it ("should create 3 objects from 3 items in map return") {
  77. val ls1 = couch(carDb view(
  78. Views builder("car_views/red_cars") build))
  79. println(ls1)
  80. ls1.size should equal(3)
  81. import dispatch.json.Js._;
  82. val objs =
  83. ls1.map { car =>
  84. val x = Symbol("value") ? obj
  85. val x(x_) = car
  86. JsBean.toBean(x_, classOf[CarSaleItem])._3
  87. }
  88. objs.size should equal(3)
  89. objs.map(_.make).sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List("BMW", "Geo", "Honda"))
  90. }
  91. }
  92. describe("Returning objects directly from view results (map only)") {
  93. it ("should create 3 car objects from 3 items in map return") {
  94. val ls1 = couch(carDb view(
  95. Views builder("car_views/red_cars") build, classOf[CarSaleItem]))
  96. println(ls1)
  97. ls1.size should equal(3)
  98. ls1.map(_.make).sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List("BMW", "Geo", "Honda"))
  99. }
  100. it ("should create 3 number objects from 3 items in map return") {
  101. val ls1 = couch(carDb view(
  102. Views builder("car_views/red_cars_price") build, classOf[BigDecimal]))
  103. println(ls1)
  104. ls1.size should equal(3)
  105. ls1.sort((e1, e2) => (e1 compareTo e2) < 0) should equal(List(7500, 12500, 16000))
  106. }
  107. }
  108. describe("Create, query, view : map and reduce") {
  109. it("should identify red cars") {
  110. // map function
  111. val redCarsPrice =
  112. """(doc: dispatch.json.JsValue) => {
  113. val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
  114. if (car.color.contains("Red")) List(List(car.make, car.price)) else Nil
  115. }"""
  116. val redfn1 = """(key: List[(String, String)], values: List[dispatch.json.JsNumber], rereduce: Boolean) => {
  117. values.foldLeft(BigDecimal(0.00))((s, f) => s + (f match { case dispatch.json.JsNumber(n) => n }))
  118. }"""
  119. val redCarsPriceView = new View(redCarsPrice, redfn1)
  120. val cv = DesignDocument("red_car_views", null, Map[String, View]())
  121. cv.language = "scala"
  122. val rcv = DesignDocument(cv._id, null, Map("red_cars_price" -> redCarsPriceView))
  123. rcv.language = "scala"
  124. couch(Doc(carDb, rcv._id) add rcv)
  125. val ls2 = couch(carDb view(
  126. Views builder("red_car_views/red_cars_price") build))
  127. println(ls2)
  128. ls2.size should equal(1)
  129. }
  130. }
  131. describe("Create, query, view : map and reduce objects created after returning JSON from view") {
  132. it("should identify red cars and find sum of price") {
  133. // map function
  134. val mapForRedCars =
  135. """(doc: dispatch.json.JsValue) => {
  136. val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
  137. if (car.color.contains("Red")) List(List(car.make, car)) else Nil
  138. }"""
  139. val reduceToPriceSum = """(key: List[(String, String)], values: List[dispatch.json.JsObject], rereduce: Boolean) => {
  140. val objs = values.map(couch.json.JsBean.toBean(_, classOf[couch.db.CarSaleItem])._3).map(_.price)
  141. objs.foldLeft(BigDecimal(0.00))(_+_)
  142. }"""
  143. val redCarsPriceView = new View(mapForRedCars, reduceToPriceSum)
  144. val cv = DesignDocument("sum_car_views", null, Map[String, View]())
  145. cv.language = "scala"
  146. val rcv = DesignDocument(cv._id, null, Map("red_cars_sum_price" -> redCarsPriceView))
  147. rcv.language = "scala"
  148. couch(Doc(carDb, rcv._id) add rcv)
  149. val ls1 = couch(carDb view(
  150. Views builder("sum_car_views/red_cars_sum_price") build))
  151. println(ls1)
  152. ls1.size should equal(1)
  153. import dispatch.json.Js._
  154. import dispatch.json._
  155. val objs =
  156. ls1.map { mp =>
  157. val x = Symbol("value") ? num
  158. val x(x_) = mp
  159. x_
  160. }
  161. objs.size should equal(1)
  162. objs.head should equal(36000)
  163. }
  164. it("should identify red cars and find max price") {
  165. // map function to spit out red cars
  166. val mapForRedCars =
  167. """(doc: dispatch.json.JsValue) => {
  168. val (id, rev, car) = couch.json.JsBean.toBean(doc, classOf[couch.db.CarSaleItem]);
  169. if (car.color.contains("Red")) List(List(car.make, car)) else Nil
  170. }"""
  171. // reduce function to get max price
  172. val reduceToMaxPrice = """(key: List[(String, String)], values: List[dispatch.json.JsObject], rereduce: Boolean) => {
  173. values.map(couch.json.JsBean.toBean(_, classOf[couch.db.CarSaleItem])._3).map(_.price).sort((e1,e2) => (e1 > e2)).head
  174. }"""
  175. val redCarsPriceView = new View(mapForRedCars, reduceToMaxPrice)
  176. val cv = DesignDocument("max_car_views", null, Map[String, View]())
  177. cv.language = "scala"
  178. val rcv = DesignDocument(cv._id, null, Map("red_cars_max_price" -> redCarsPriceView))
  179. rcv.language = "scala"
  180. couch(Doc(carDb, rcv._id) add rcv)
  181. val ls1 = couch(carDb view(
  182. Views builder("max_car_views/red_cars_max_price") build))
  183. println(ls1)
  184. ls1.size should equal(1)
  185. import dispatch.json.Js._
  186. import dispatch.json._
  187. val objs =
  188. ls1.map { mp =>
  189. val x = Symbol("value") ? num
  190. val x(x_) = mp
  191. x_
  192. }
  193. objs.size should equal(1)
  194. objs.head should equal(16000)
  195. }
  196. }
  197. describe("Returning objects directly from view results in reduce") {
  198. it ("should create 1 number objects from reduce") {
  199. val ls1 = couch(carDb view(
  200. Views builder("max_car_views/red_cars_max_price") build, classOf[BigDecimal]))
  201. println(ls1)
  202. ls1.size should equal(1)
  203. ls1(0) should equal(16000)
  204. }
  205. }
  206. }
  207. import scala.reflect._
  208. @BeanInfo
  209. case class CarSaleItem(make : String, model : String, price : BigDecimal, condition : String, color : String) {
  210. def this(make : String, model : String, price : Int, condition : String, color : String) =
  211. this(make, model, BigDecimal.int2bigDecimal(price), condition, color)
  212. private [db] def this() = this(null, null, 0, null, null)
  213. override def toString = "A " + condition + " " + color + " " + make + " " + model + " for $" + price
  214. }
  215. @BeanInfo
  216. case class ItemPrice(store: String, item: String, price: Number) {
  217. private [db] def this() = this(null, null, null)
  218. override def toString = "shop = " + store + " for item " + item + " @ " + price
  219. }