Coder Social home page Coder Social logo

foursquare / rogue Goto Github PK

View Code? Open in Web Editor NEW
487.0 192.0 77.0 3.65 MB

MOVED - The project is still under development but this page is deprecated.

Home Page: https://github.com/foursquare/fsqio

License: Other

Scala 99.25% Thrift 0.07% Shell 0.68%

rogue's Introduction

NOTICE - This project has moved.

It is now part of Foursquare's open source monorepo Fsq.io and all future work will be published there.

The project lives on but this Github repo is deprecated.

Rogue

Rogue is a type-safe internal Scala DSL for constructing and executing find and modify commands against MongoDB in the Lift web framework. It is fully expressive with respect to the basic options provided by MongoDB's native query language, but in a type-safe manner, building on the record types specified in your Lift models. An example:

Venue.where(_.mayor eqs 1234).and(_.tags contains "Thai").fetch(10)

The type system enforces the following constraints:

  • the fields must actually belong to the record (e.g., mayor is a field on the Venue record)
  • the field type must match the operand type (e.g., mayor is an IntField)
  • the operator must make sense for the field type (e.g., categories is a MongoListField[String])

In addition, the type system ensures that certain builder methods are only used in certain circumstances. For example, take this more complex query:

Venue.where(_.closed eqs false).orderAsc(_.popularity).limit(10).modify(_.closed setTo true).updateMulti

This query purportedly finds the 10 least popular open venues and closes them. However, MongoDB does not (currently) allow you to specify limits on modify queries, so Rogue won't let you either. The above will generate a compiler error.

Constructions like this:

def myMayorships = Venue.where(_.mayor eqs 1234).limit(5)
...
myMayorships.fetch(10)

will also not compile, here because a limit is being specified twice. Other similar constraints are in place to prevent you from accidentally doing things you don't want to do anyway.

Installation

Because Rogue is designed to work with several versions of lift-mongodb-record, you'll want to declare your dependency on Rogue as intransitive and declare an explicit dependency on the version of Lift you want to target. In sbt, that would look like the following:

val rogueField      = "com.foursquare" %% "rogue-field"         % "2.5.0" intransitive()
val rogueCore       = "com.foursquare" %% "rogue-core"          % "2.5.1" intransitive()
val rogueLift       = "com.foursquare" %% "rogue-lift"          % "2.5.1" intransitive()
val rogueIndex      = "com.foursquare" %% "rogue-index"         % "2.5.1" intransitive()
val liftMongoRecord = "net.liftweb"    %% "lift-mongodb-record" % "2.6"

Rogue 2.5.x requires Lift 2.6-RC1 or later. For support for earlier versions of Lift, use Rogue 2.4.0 or earlier. If you encounter problems using Rogue with other versions of Lift, please let us know.

Join the rogue-users google group for help, bug reports, feature requests, and general discussion on Rogue.

Setup

Define your record classes in Lift like you would normally (see TestModels.scala for examples).

Then anywhere you want to use rogue queries against these records, import the following:

import com.foursquare.rogue.LiftRogue._

See EndToEndTest.scala for a complete working example.

More Examples

QueryTest.scala contains sample Records and examples of every kind of query supported by Rogue. It also indicates what each query translates to in MongoDB's JSON query language. It's a good place to look when getting started using Rogue.

NB: The examples in QueryTest only construct query objects; none are actually executed. Once you have a query object, the following operations are supported (listed here because they are not demonstrated in QueryTest):

For "find" query objects

val query = Venue.where(_.venuename eqs "Starbucks")
query.count()
query.countDistinct(_.mayor)
query.fetch()
query.fetch(n)
query.get()     // equivalent to query.fetch(1).headOption
query.exists()  // equivalent to query.fetch(1).size > 0
query.foreach{v: Venue => ... }
query.paginate(pageSize)
query.fetchBatch(pageSize){vs: List[Venue] => ...}
query.bulkDelete_!!(WriteConcern.SAFE)
query.findAndDeleteOne()
query.explain()
query.iterate(handler)
query.iterateBatch(batchSize, handler)

For "modify" query objects

val modify = query.modify(_.mayor_count inc 1)
modify.updateMulti()
modify.updateOne()
modify.upsertOne()

for "findAndModify" query objects

val modify = query.where(_.legacyid eqs 222).findAndModify(_.closed setTo true)
modify.updateOne(returnNew = ...)
modify.upsertOne(returnNew = ...)

Releases

The latest release is 2.5.1. See the changelog for more details.

Dependencies

lift-mongodb-record, mongodb, joda-time, junit. These dependencies are managed by the build system.

Maintainers

Rogue was initially developed by Foursquare Labs for internal use -- nearly all of the MongoDB queries in foursquare's code base go through this library. The current maintainers are:

Contributions welcome!

rogue's People

Contributors

alexflav23 avatar d6y avatar eiennohito avatar foursquare-markcc avatar heralight avatar hoffrocket avatar indrajitr avatar jliszka avatar jonshea avatar jorgeortiz85 avatar ktoso avatar leothekim avatar mateor avatar mattpap avatar ms-tg avatar paulfryzel avatar slackhappy avatar tjulien avatar viktortnk avatar zaneli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rogue's Issues

Scala 2.11.x support

It seems that Rogue does not currently have support for Scala 2.11 โ€” are there any plans to add it?

Query#toString returns invalid Mongo query

This

Job.where(_._id eqs search).toString

yields

db.jobs.find({ "_id" : { "$oid" : "52f064dcef86abdf52155300"}})

Executing that on the Mongo shell:

> db.jobs.find({ "_id" : { "$oid" : "52f064dcef86abdf52155300"}})
error: { "$err" : "invalid operator: $oid", "code" : 10068 }

...because it should really be db.jobs.find({ "_id" : ObjectId("52f064dcef86abdf52155300")}).

fetch-ing this one works fine though... It's just that sometimes for debugging it's good to get the raw query and be able to execute it manually.


I tried to understand how the query is built prior to being executed but ExecutableQuery/QueryExecutor/LiftQueryExecutor/etc is just too complicated to understand in less than a couple of ours with no prior familiarity... However, Query#toString definitely doesn't seem to be using the same mechanism for JSON'izing the query as Query#fetch.

Why not use git tags?

It would be great if this project adopted the practice of pushing a (git tag)[http://learn.github.com/p/tagging.html] for each released version -- it makes it super easy to go to the source version that corresponds to a released version.

It's such a simple step, and it would be a great help to us users of the library.

Two ors

Hi,

In mongo is possible to write query with two or's like:

db.someCollection.find({ $or : [ { "system" : "test1" } , { "system" : "test2" } ] ,
$or : [ { "something" : true } , { "something" : false } , { "something" : { $exists : false } }]
})

( I know that this specific query could be wrote in one or but I have much much more complicated query and I need to user or parameter two times ).

But lift rogue when compiling shows me and error:

Query must be HasNoOrClause, but it's actually com.foursquare.rogue.Unselected with com.foursquare.rogue.ShardKeyNotSpecified with com.foursquare.rogue.Unordered with com.foursquare.rogue.Unskipped with com.foursquare.rogue.Unlimited with com.foursquare.rogue.HasOrClause

is it possible in lift rogue write such query ?
Thanks!

JFYI: IntelliJ erroneously thinking that subfield queries don't compile

Note for other weary travelers: I've noticed IntelliJ's Scala plugin failing to understand Rogue sub-field queries:

Full error:

Assuming that IntelliJ was correct, I almost gave up and assumed that Rogue subfield queries don't work (this is at the v3.0.0-beta13.1 tag, which seems to have a pretty different syntax for subfield queries than what is documented?), but luckily I noticed that my running sbt ~compile was finishing successfully.

I'll file this against IntelliJ or the Scala plugin.. "soon", but wanted to leave a note here about it too.

GridFS and querying

Hi!

I'm working with GridFS and using Rogue for querying file records. GridFS has one issue - its record doesn't support partial state.
MongoHelpers has such code:

val sel = queryClause.select.map(buildSelect) getOrElse
                buildSelectFromNames(queryClause.meta.metaFields.view.map(_.name))

So DBCursor will always created in partial state (because list of fields is present). So it is impossible to work with gridfs with Rogue.
Can sel be set to null if select() is not specified?
Thank you!

SBT is unable to resolve Lift dependencies for Rogue.

 "com.foursquare" %% "rogue-field" % "2.1.0",
 "com.foursquare" %% "rogue-core" % "2.1.0",
 "com.foursquare" %% "rogue-lift" % "2.1.0"

These depend on Lift 2.5-SNAPSHOT when using Scala 2.10. I believe published Lift artefacts have changed naming policy, as SBT is unable to resolve Lift 2.5-SNAPSHOT using all the below channels:

resolvers ++= Seq(
    "Sonatype repo"      at "https://oss.sonatype.org/content/groups/scala-tools/",
    "Sonatype releases"  at "https://oss.sonatype.org/content/repositories/releases",
    "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
    "Sonatype staging"       at "http://oss.sonatype.org/content/repositories/staging"

Failure was detected on a couple servers and machines without explicitly changing setup anywhere. Our CI servers reported build failures starting with last night.

Serialization error when List is passed as argument to eqs, neq

I have a collection whose documents have an array field. I want to query against that field explicitly comparing to an array argument. In this case, I want to compare it to an empty list, so I can pull back only documents that have non-empty array values. But when I try to write this query against Rogue, I get an error when mongodb JSON tries to serialize the List argument:

scala> MyCollection.scan(.myArrayField exists true).scan(.myArrayField neqs Nil)
java.lang.RuntimeException: json can't serialize type : class scala.collection.immutable.Nil$
at com.mongodb.util.JSON.serialize(JSON.java:262)
at com.mongodb.util.JSON.serialize(JSON.java:141)
at com.mongodb.util.JSON.serialize(JSON.java:141)
at com.mongodb.util.JSON.serialize(JSON.java:58)
at com.mongodb.BasicDBObject.toString(BasicDBObject.java:84)
at com.foursquare.rogue.MongoHelpers$MongoBuilder$.buildQueryString(MongoHelpers.scala:97)
at com.foursquare.rogue.Query.toString(Query.scala:225)

The equivalent mongo query run directly against mongo console works and returns the expected results:
db.MyCollection.find({myArrayField:{$ne: [], $exists: true}})

How to use 2+ top-level OR clauses

Hi Jason,

In mongo, it is possible to provide multiple top-level $or queries, the results of which are implicitly AND'ed together, right?

For example, imagine that you have two renamed fields, and you want to query both the old and new fields, you might write:

db.coll.find{ "$or": [ { "newFieldOne": "fieldValueOne" }, { "oldFieldOne": "fieldValueOne" } ],
                      "$or": [ { "newFieldTwo": "fieldValueTwo" }, { "oldFieldTwo": "fieldValueTwo" } ],
                      "otherField": { "$lt": 2 } };

This should return these rows:

{ "newFieldOne": "fieldValueOne", "oldFieldTwo": "fieldValueTwo", "otherField": 1 },
{ "oldFieldOne": "fieldValueOne", "newFieldTwo": "fieldValueTwo", "otherField": 1 }

But should not return these rows:

{ "newFieldOne": "fieldValueOne", "oldFieldTwo": "fieldValueTwo", "otherField": 3 },  // otherField is not less than 2
{ "oldFieldOne": "foo", "newFieldTwo": "fieldValueTwo", "otherField": 1 } // neither oldFieldOne nor newFieldOne equals fieldValueOne

AFAICT, this query form is supported in Mongo since at least 1.6.x, but I cannot find any way to express this query in Rogue. Is it possible?

Thanks,
-Marc

Bad symbolic reference in RC4

After upgrading to RC-4 i get, using Lift 2.5-RC5:

[error] bad symbolic reference. A signature in LiftRogue.class refers to type IndexBuilder
[error] in package com.foursquare.rogue.index which is not available.
[error] It may be completely missing from the current classpath, or the version on
[error] the classpath might be incompatible with the version used when compiling LiftRogue.class.

MongoDB Aggregation

Are there any plans to support the MongoDB aggregation framework and map-reduce queries?

Unexpected behavior: 'matches' and 'nin'

Hi!

I have such query:

Model where (_.field matches pattern) and (_.field nin excluding)

It becomes:

db.models.find({ "field" : { "$regex" : "\\Qstr\\E" , "$options" : "i"}})

but i'm expecting:

db.models.find({ "field" : { "$regex" : "\\Qstr\\E" , "$options" : "i", "$nin" : ["str1","str2"]}})

As i understand the reason is matches creates EqClause and this clause is alone.

Query with optional where clause, in or clause, generates wrong query

Hey guys,
seems we encountered a bug in building a specific query, example bellow:

MyMeta
      .or(
        _.where(_.things in List(thing)),
        _.whereOpt(additionalThing))(_.additionalThings in List(_))
      )

Which generates such query (additionalThing = None):

... "$or": [ { "things" : { "$in" : [ "thingA"]}} , { }]},  ...

What we don't like here is the { } part in the or. We'd rather just have it left out.
This makes the query fetch the entire collection so we had to fallback to manual building of or if it's needed.

Cheers and thanks for the great lib :)
Konrad

rawOpt ?

Is this possible?

Venue where (_.mayor eqs 1) rawOpt(Some(3)) (_.add("$where", "this.a > %d".format(_))) toString() must_== """db.venues.find({ "mayor" : 1 , "$where" : "this.a > 3"})"""
Venue where (_.mayor eqs 1) rawOpt(None) (_.add("$where", "this.a > %d".format(_))) toString() must_== """db.venues.find({ "mayor" : 1})"""

Unresolved dependency using sbt (0.10.1)

Putting "com.foursquare" %% "rogue" % "1.0.15" in my build.sbt produces

`sbt.ResolveException: unresolved dependency: net.liftweb#lift-mongodb-record_2.9.0;2.4-SNAPSHOT: not found`

This happens with 1.0.15-1.0.18 and 1.0.19-SNAPSHOT.

Looking through scala-tools.org, it appears that there is no lift-mongodb-record in the snapshot (http://scala-tools.org/repo-snapshots/net/liftweb/lift-mongodb_2.9.0/2.4-SNAPSHOT/). Maybe 2.4-M3 should be used instead as it is more stable.

$position push modifier support

Add support for $position modifier as described here http://docs.mongodb.org/manual/reference/operator/update/position/

We probably just need to something like

class ModifyPushEachPositionClause(fieldName: String, position: Int, values: Traversable[_])
    extends ModifyClause(ModOps.Push) {
  override def extend(q: BasicDBObjectBuilder): Unit = {
    q.push(fieldName).add("$each", QueryHelpers.list(values)).add("$position", position).pop
  }
}

class ModifyPushEachSliceClause(fieldName: String, slice: Int, position: Int, values: Traversable[_])
    extends ModifyClause(ModOps.Push) {
  override def extend(q: BasicDBObjectBuilder): Unit = {
    q.push(fieldName).add("$each", QueryHelpers.list(values)).add("$slice", slice).add("$position", position).pop
  }
}

$where clause support (javascript functions and shorthand SQL-like strings)

Rogues doesn't appear to support the use of $where clauses, which allow you to add arbitrary javascript functions to mongo querying, as well as using a short-hand SQL-like syntax.
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-JavascriptExpressionsand{{%24where}}
http://www.mongodb.org/display/DOCS/Server-side+Code+Execution#Server-sideCodeExecution-{{%24where}}ClausesandFunctionsinQueries

Why is this important?

In mongo, there are current use cases which require the use of $where clauses, as the built-in mongo queries cannot handle them. For example, it is impossible to query records for which ALL members of their embedded lists meet a criteria:
http://stackoverflow.com/questions/6038818/mongodb-query-to-match-each-element-in-doc-array-to-a-condition

Cases such as these require using a $where clause with a custom javascript function, which thankfully will only be executed for records which satisfy the build-in mongo queries.

So, for example, I'd like to be able to ask mongo whether ALL of a Venue's tags start with "prefix" -- that being just an example of a constraint that must be true for ALL of the items in an embedded array in the record.

Venue where (_.mayor eqs 1) andJavascript("function() { for (t in obj.tags) { if !(/^prefix/).test(t) return false; }; return true; }")

And this should return all Venue records where (mayor == 1), and ALL elements of the embedded tag list start with "prefix".

Is there currently a way to do this with Rogue?

Query#or is broken

Job.where(_.jobId eqs foo).or(_.where(_._id eqs ObjectId(foo))).signature results in:

db.jobs.find({ "JOB_ID" : 0 , "$or" : [ { "_id" : 0}]})

instead of

db.jobs.find({ "$or": [{"JOB_ID" : 0} , { "_id" : 0}]})

on closer inspection, looks like in order to get a correct $or query out of rogue, one has to do this instead:

Job.or(
  _.where(_.jobId eqs foo),
  _.where(_._id eqs new org.bson.types.ObjectId(foo)))

which yields the correct

db.jobs.find({ "$or" : [ { "JOB_ID" : 0} , { "_id" : 0}]})

however, https://github.com/foursquare/rogue/blob/master/rogue-lift/src/test/scala/com/foursquare/rogue/QueryTest.scala says:

Venue.where(_.mayor eqs 1).or(_.where(_._id eqs oid)).signature() must_== """db.venues.find({ "mayor" : 0 , "$or" : [ { "_id" : 0}]})"""

NoSuchMethodError: MongoIdentifier

I previously was using Lift 2.5.1, Rogue 2.2.0, and was trying to upgrade to Lift 2.6 RC1, Rogue 2.4.0.

I'm getting the following error when trying to perform any queries using the upgraded packages:

java.lang.NoSuchMethodError: net.liftweb.mongodb.MongoMeta.mongoIdentifier()Lnet/liftweb/mongodb/MongoIdentifier;
at com.foursquare.rogue.LiftDBCollectionFactory$.getInstanceName(LiftQueryExecutor.scala:27)
at com.foursquare.rogue.MongoJavaDriverAdapter.runCommand(MongoJavaDriverAdapter.scala:27)
at com.foursquare.rogue.MongoJavaDriverAdapter.doQuery(MongoJavaDriverAdapter.scala:274)
at com.foursquare.rogue.MongoJavaDriverAdapter.query(MongoJavaDriverAdapter.scala:169)
at com.foursquare.rogue.QueryExecutor$class.fetch(QueryExecutor.scala:65)
at com.foursquare.rogue.LiftQueryExecutor.fetch(LiftQueryExecutor.scala:36)
at com.foursquare.rogue.ExecutableQuery.fetch(ExecutableQuery.scala:57)
at .(:12)
at .()
at .(:7)
at .()
at $print()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983)
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604)
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568)
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:760)
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:805)
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:717)
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:581)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:588)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:591)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:882)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837)
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:837)
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:904)
at org.jetbrains.plugins.scala.compiler.rt.ConsoleRunner.main(ConsoleRunner.java:64)

There is a related post along with some of the workarounds here: https://groups.google.com/forum/#!msg/liftweb/QSsjKLjhR9g/PouK-phiuuQJ

but I was wondering if you were going to update the main trunk of Rogue to solve this issue anytime soon. Thanks,

Rogue treats EnumField in nested document as String when used in query condition

Hi, I'm using the latest 2.2.0 version and it seems I found a bug. Here is how to reproduce it:

import net.liftweb.mongodb.record.BsonRecord
import net.liftweb.record.field.EnumField
import net.liftweb.mongodb.record.BsonMetaRecord
import net.liftweb.mongodb.record.MongoRecord
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.mongodb.record.field.BsonRecordField
import wws.db.connection.MongoConfig
import net.liftweb.mongodb.record.MongoMetaRecord
import com.foursquare.rogue.LiftRogue._

// Enum that "causes throuble"
object TestEnum extends Enumeration {
  type TestEnum = Value
  val ONE, TWO = Value
}

import TestEnum._

// Model classes
class NestedDoc extends BsonRecord[NestedDoc] {
  def meta = NestedDoc
  // the same field type as 'goodField' but Rogue converts it to String in queries
  object thisFieldIsNotAString extends EnumField(this, TestEnum)
}
object NestedDoc extends NestedDoc with BsonMetaRecord[NestedDoc]

class TestDbClass extends MongoRecord[TestDbClass] with ObjectIdPk[TestDbClass] {
  override def meta = TestDbClass
  object goodField extends EnumField(this, TestEnum) // this field works just fine
  object badField extends BsonRecordField(this, NestedDoc)
}
object TestDbClass extends TestDbClass with MongoMetaRecord[TestDbClass] {
  override def mongoIdentifier = MongoConfig.identifier.vend
}

// The app that tests this scenario
object TestDbApp extends App {

  def printDocWithFields(doc: TestDbClass): Unit = {
    println(doc)
    println(doc.goodField.get.getClass)
    println(doc.badField.get.thisFieldIsNotAString.get.getClass)
  }

  MongoConfig.init()

  val doc = TestDbClass.createRecord
    .goodField(ONE)
    .badField(NestedDoc.createRecord.thisFieldIsNotAString(ONE))
  println("\n\nDoc before Save:")
  printDocWithFields(doc)
  val docDb = doc.saveTheRecord().get
  val docId = docDb.id.get
  println("\n\nDoc after Save:")
  printDocWithFields(docDb)

  val query = TestDbClass.where(_.goodField eqs ONE)
    .and(_.badField.subfield(_.thisFieldIsNotAString) eqs TWO)
  println("\n\nQuery:")
  println(query)
  println("Good field type: " + query.asDBObject.get("goodField").getClass)
  println("Bad field type: " +     query.asDBObject.get("badField.thisFieldIsNotAString").getClass)

  val docDbRefetch = TestDbClass.find(docId).head
  println("\n\nDoc fetched with Java driver:")
  printDocWithFields(docDbRefetch)

  val docDbFetchWithRogue = TestDbClass.where(_.id eqs docId)
    .and(_.goodField eqs ONE).fetch().head
  println("\n\nDoc fetched with Rogue using good field:")
  printDocWithFields(docDbFetchWithRogue)

  val docDbFetchWithRogueBadField = TestDbClass.where(_.id eqs docId)
    .and(_.badField.subfield(_.thisFieldIsNotAString) eqs ONE).fetch()
  println("\n\nDoc fetched with Rogue using bad field:")
  docDbFetchWithRogueBadField match {
    case expected :: _ => printDocWithFields(expected) // Desired behavior
    case List() => println("Didn't find the doc!!!") // Current behavior (bug?)
  }
}

I've noticed these comments in src/test/scala/com/foursquare/rogue/EndToEndTest.scala:

// This behavior is broken because we get a String back from mongo, and at
// that point we only have a DummyField for the subfield, and that doesn't
// know how to convert the String to an Enum.

However, this seems to be a different issue, could you confirm?

Thanks

p.s. I can write a test and submit a pull request if it helps.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.