All Downloads are FREE. Search and download functionalities are using the official Maven repository.

molecule.boilerplate.api.Keywords.scala Maven / Gradle / Ivy

The newest version!
package molecule.boilerplate.api

/** Keywords to mark aggregate expressions on and unifications of attributes.
 * {{{
 * // Aggregates on any attribute type
 * Person.age(count).get.map(_.head ==> 3)         // count of asserted `age` attribute values
 * Person.age(countDistinct).get.map(_.head ==> 3) // count of asserted distinct `age` attribute values
 * Person.age(max).get.map(_.head ==> 38)          // maximum `age` value (using `compare`)
 * Person.age(min).get.map(_.head ==> 5)           // maximum `age` value (using `compare`)
 * Person.age(sample).get.map(_.head ==> 27)       // single sample `age` value
 *
 * // Aggregates on any attribute type, returning multiple values
 * Person.age(distinct).get.map(_.head ==> Vector(5, 7, 38)) // distinct `age` values
 * Person.age(max(2)).get.map(_.head ==> Vector(38, 7))      // 2 maximum `age` values
 * Person.age(min(2)).get.map(_.head ==> Vector(5, 7))       // 2 minimum `age` values
 * Person.age(sample(2)).get.map(_.head ==> Vector(7, 38))   // 2 sample `age` values
 *
 * // Aggregates on number attributes
 * Person.age(sum).get.map(_.head ==> 50)                  // sum of all `age` numbers
 * Person.age(avg).get.map(_.head ==> 16.66666667)         // average of all `age` numbers
 * Person.age(median).get.map(_.head ==> 7)                // median of all `age` numbers
 * Person.age(stddev).get.map(_.head ==> 15.107025591499)  // standard deviation of all `age` numbers
 * Person.age(variance).get.map(_.head ==> 228.2222222222) // variance of all `age` numbers
 * }}}
 *
 * @groupname aggregates Aggregate keywords
 * @groupdesc aggregates
 *            Keywords applied to attributes that return aggregated value(s).
 * @groupprio aggregates 30
 * @groupname aggrNumber Number aggregation keywords
 * @groupdesc aggrNumber
 *            Keywords applied to number attributes that return aggregated value(s).
 * @groupprio aggrNumber 31
 */
trait KeywordsStable {

  trait Kw

  trait AggrKw extends Kw
  trait AggrCoalesce extends AggrKw
  trait AggrInt extends AggrKw

  /** Distinct attribute values. 

Apply `distinct` keyword to attribute * to return Vector of distinct attribute values of entities matching the * molecule. * {{{ * for { * _ <- Person.firstName.lastName.age insert List( * ("Ben", "Hayday", 42), * ("Liz", "Taylor", 34), * ("Liz", "Swifty", 34), * ("Liz", "Mooray", 25) * ) * _ <- Person.firstName.age(distinct) insert List( * ("Ben", 42), * ("Liz", Vector(34, 25)) // only single 34 returned * ) * } yield () * }}} * * @return * List[attribute-type] * @group aggregates */ trait distinct extends AggrKw /** Minimum attribute value(s).

Apply `min` keyword to attribute to * return the minimum attribute value of entities matching the molecule. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(min).get.map(_.head ==> 25) * } yield () * }}} * Apply `min(n)` to return Vector of the n smallest values. * {{{ * Person.age(min(3)).get.map(_.head ==> Vector(25, 34, 37)) * }}} * * @note * `min`/`min(n)` supports all value types (via comparators).
`min(n)` * Can at most return the number of values that match. * @group aggregates */ trait min extends AggrKw { /** Minimum n values of attribute.

Apply `min(n)` to attribute to * return Vector of the n smallest values of entities matching the * molecule. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(min(2)).get.map(_.head ==> List(25, 34)) * } yield () * }}} * * @note * `min`/`min(n)` supports all value types (via comparators).
Can at * most return the number of values that match. * @return * List[attribute-type] */ def apply(i: Int): mins = mins(i) } case class mins(n: Int) extends Kw { override def toString = "mins" } /** Maximum attribute value(s).

Apply `max` keyword to attribute to * return the maximum attribute value of entities matching the molecule. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(max).get.map(_.head ==> 70) * } yield () * }}} * Apply `max(n)` to return Vector of the n biggest values. * {{{ * Person.age(max(3)).get.map(_.head ==> Vector(37, 42, 70)) * }}} * * @note * `max`/`max(n)` supports all value types (via comparators).
`max(n)` * Can at most return the number of values that match. * @group aggregates */ trait max extends AggrKw { /** Maximum n values of attribute.

Apply `max(n)` to attribute to * return Vector of the n biggest values of entities matching the molecule. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(max(3)).get.map(_.head ==> List(37, 42, 70)) * } yield () * }}} * * @note * `max`/`max(n)` supports all value types (via comparators).
Can at * most return the number of values that match. * @return * List[attribute-type] */ def apply(i: Int): maxs = maxs(i) } case class maxs(n: Int) extends Kw { override def toString = "maxs" } /** Sample attribute value(s).

Apply `sample` keyword to attribute to * return a single sample (random) attribute value of entities matching the * molecule. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(sample).get.map(_.head ==> 42) // or other.. * } yield () * }}} * Apply `sample(n)` to return Vector of up to n distinct sample values. * {{{ * Person.age(sample(3)).get.map(_.head ==> Vector(70, 25, 37)) // or other.. * }}} * * @note * Can at most return the number of values that match. * @group aggregates */ trait sample extends AggrKw { /** Distinct sample values of attribute.

Apply `sample(n)` to an * attribute to return a Set of up to n sample values. * {{{ * for { * _ <- Person.age.insert(25, 34, 37, 42, 70) * _ <- Person.age(sample(3)).get.map(_.head ==> Vector(42, 25, 42)) // or other.. * } yield () * }}} * * @note * Can at most return the number of values that match. * @return * List[attribute-type] * @group aggregates */ def apply(n: Int): samples = samples(n) } case class samples(n: Int) extends Kw { override def toString = "samples" } /** Count of attribute values.

Apply `count` keyword to attribute to * return count of attribute values of entities matching the molecule. * {{{ * for { * _ <- Person.firstName.lastName.age insert List( * ("Ben", "Hayday", 42), * ("Liz", "Taylor", 34), * ("Liz", "Swifty", 34), * ("Liz", "Mooray", 25) * ) * _ <- Person.firstName.age(count).get.map(_ ==> List( * ("Ben", 1), * ("Liz", 3) // 34, 34, 25 * )) * } yield () * }}} * * @return * Int * @group aggregates */ trait count extends AggrCoalesce with AggrInt /** Count of distinct attribute values.

Apply `countDistinct` keyword * to attribute to return count of distinct attribute values of entities * matching the molecule. * {{{ * for { * _ <- Person.firstName.lastName.age insert List( * ("Ben", "Hayday", 42), * ("Liz", "Taylor", 34), * ("Liz", "Swifty", 34), * ("Liz", "Mooray", 25) * ) * _ <- Person.firstName.age(countDistinct).get.map(_ ==> List( * ("Ben", 1), * ("Liz", 2) // 34, 25 * )) * } yield () * }}} * * @return * Int * @group aggregates */ trait countDistinct extends AggrCoalesce /** Sum of attribute values.

Apply `sum` keyword to attribute to * return sum of attribute values of entities matching the molecule. * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 4) * _ <- Match.score(sum).get.map(_.head ==> 7) * } yield () * }}} * * @return * Value of Attribute type * @group aggrNumber */ trait sum extends AggrCoalesce /** Median of attribute values.

Apply `median` keyword to attribute * to return median of attribute values of entities matching the molecule. * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 4) * _ <- Match.score(median).get.map(_.head ==> 2) * } yield () * }}} * OBS: When it comes to an even number of values, Datomic has a special * implementation of median that is different from the one described on the * [[https://en.wikipedia.org/wiki/Median Wiki entry on the median function]]. *

Datomic calculates the median of even number of values as the * average of the two middle numbers rounded down to nearest whole number * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 3, 4) * _ <- Match.score(median).get.map(_.head ==> 2) // (2 + 3) / 2 = 2.5 rounded down to 2 * } yield () * }}} * With decimal numbers this can go wrong: * {{{ * for { * _ <- Match.sKeywords.insert(1.0, 2.5, 2.5, 3.0) * _ <- Match.score(median).get.map(_.head ==> 2) // (2.5 + 2.5) / 2 = 2.5 rounded down to 2 (This is wrong and bug report has been filed) * } yield () * }}} * * @return * Value of Attribute type * @group aggrNumber */ trait median extends AggrCoalesce /** Average of attribute values.

Apply `avg` keyword to attribute to * return average of attribute values of entities matching the molecule. * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 4) * _ <- Match.score(avg).get.map(_.head ==> 2.3333333333333335) // (1 + 2 + 4) / 3 * } yield () * }}} * * @return * Double * @group aggrNumber */ trait avg extends AggrCoalesce /** Variance of attribute values.

Apply `variance` keyword to * attribute to return variance of attribute values of entities matching the * molecule. * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 4) * _ <- Match.score(variance).get.map(_.head ==> 1.5555555555555556) * } yield () * }}} * * @return * Double * @group aggrNumber */ trait variance extends AggrCoalesce /** Variance of attribute values.

Apply `stddev` keyword to attribute * to return variance of attribute values of entities matching the molecule. * {{{ * for { * _ <- Match.sKeywords.insert(1, 2, 4) * _ <- Match.score(stddev).get.map(_.head ==> 1.247219128924647) * } yield () * }}} * * @return * Double * @group aggrNumber */ trait stddev extends AggrCoalesce } object Keywords extends KeywordsStable trait Keywords { // Common for all types object distinct extends Keywords.distinct { override def toString = "distinct" } object min extends Keywords.min { override def toString = "min" } object max extends Keywords.max { override def toString = "max" } object sample extends Keywords.sample { override def toString = "sample" } object count extends Keywords.count { override def toString = "count" } object countDistinct extends Keywords.countDistinct { override def toString = "countDistinct" } // Number aggregators object sum extends Keywords.sum { override def toString = "sum" } object median extends Keywords.median { override def toString = "median" } object avg extends Keywords.avg { override def toString = "avg" } object variance extends Keywords.variance { override def toString = "variance" } object stddev extends Keywords.stddev { override def toString = "stddev" } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy