1
votes

Having issues using the $in operator in a ReactiveMongo 0.11 query. For some reason the query returns zero documents, although I can confirm that the IDs exist. So I assume I'm not structuring this properly.

Here's my query:

val query = BSONDocument("userId" -> userId, "convoId" -> BSONDocument("$in" -> BSONArray(convoIds)))
collection.find(query).cursor[ChatDesc](ReadPreference.primaryPreferred).collect[List]()

I construct my BSONArray by applying a list:

BSONArray(List(id1, id2, ...))

Here are the IDs being used in the query:

List(5594ee9f02fb36b06e2925b155ea043bfb006c5a6a8436be, 552c784430a54cf55e07190955ea043bfb006c5a6a8436be, 55af435c9524018461f750ec55ea043bfb006c5a6a8436be...)

If I leave out the $in operator and manually check every convoIds field, I can confirm that the 3rd ID above 55af435c9524018461f750ec55ea043bfb006c5a6a8436be is in fact present many times in the collection. Additionally, the other objects meet the criteria for the userId field.

My only other guess is I need to create some sort of MongoDB secondary index on the fields?

Not sure what I'm doing wrong. Thanks!

Update

I've narrowed the problem to how I'm applying the BSONArray. If I manually paste one of the IDs like this, BSONArray("thestringID"), and run the query it is successful. Seems peculiar since I thought List was a descendant of Traversable?

3
Please indicate the versions you are using. If you have a look a the doc, you can see the - cchantep

3 Answers

2
votes

Please indicate the versions you are using.

If you have a look a the documentation, you can see the BSONArray can be created from either Traversable[BSONValue] or from Producer[BSONValue].

It seems you're list is a List[String], which is Traversable but not Traversable[BSONValue], which means it tries apply the former constructor with Producer[BSONValue]*.

Indeed, there is an instance of the type class Producer[BSONValue] for List[String], as there is one for List as soon as the element type is also provided one (which is the case for String). Such producer creates a BSONArray itself.

So the call BSONArray(List("id1","id1")) results in BSONArray(BSONArray("id1","id2")), which valid, but has no sense for the query.

0
votes

You should not use BSONArray for List, it's enough to place List in BSONDocument without anything:

val query = BSONDocument("userId" -> userId, "convoId" -> BSONDocument("$in" -> convoIds))

or in Play JSON library:

val query = Json.obj("convoId" -> Json.obj("$in" -> convoIds))
-1
votes

I had to iterate through the list since the BSONArray doesn't seem to support scala's native List.

var idFilter = BSONArray()
matchIds.foreach( id => idFilter = idFilter ++ id)
val query = BSONDocument("userId" -> userId, "convoId" -> BSONDocument("$in" -> idFilter))