0

In my MongoDB database I've a collection named "recommendation.users" in which i store all the User data. A document of my collection has the following form:

{
    "_id" : ObjectId("542e67e07f724fc2af28ba75"),
    "id" : "",
    "email" : "luigi@gmail.com",
    "tags" : [
        {
            "tag" : "Paper Goods:Liners - Baking Cups",
            "weight" : 2,
            "lastInsert" : 1412327492874
        },
        {
            "tag" : "Vegetable:Carrots - Jumbo",
            "weight" : 4,
            "lastInsert" : 1412597883569
        },
        {
            "tag" : "Paper Goods:Lialberto- Baking Cups",
            "weight" : 1,
            "lastInsert" : 1412327548205
        },
        {
            "tag" : "Fish:Swordfish Loin Portions",
            "weight" : 3,
            "lastInsert" : 1412597939124
        },
        {
            "tag" : "Vegetable:Carrots - alberto@gmail.com",
            "weight" : 2,
            "lastInsert" : 1412597939124
        }
    ]
}

As driver I'm using ReactiveMongo in Scala.

Now I'm writing a method that get a tags: List[String] and search in my collections all the Users where the "tags" elements contains all the value passed as parameter. In other words i want to find all the documents where the "tags" tag contains documents where "tag" = tags(i) for every element of tags. How can I make something like this in MongoDB and reactiveMongo??

My method has the following signature:

    def findUsers(tags: List[String]): Future[Option[List[User]]] = {
      //search all the matching Users
      //if exists at least one User return a Some(List(users))
      //otherwise returns a None

}

For example if i had the following two documents in my collection:

[
{
    "_id" : ObjectId("542e67e07f724fc2af28ba75"),
    "id" : "",
    "email" : "luigi@gmail.com",
    "tags" : [
        {
            "tag" : "Paper Goods:Liners - Baking Cups",
            "weight" : 2,
            "lastInsert" : 1412327492874
        },
        {
            "tag" : "Vegetable:Carrots - Jumbo",
            "weight" : 4,
            "lastInsert" : 1412597883569
        },
        {
            "tag" : "Paper Goods:Lialberto- Baking Cups",
            "weight" : 1,
            "lastInsert" : 1412327548205
        },
        {
            "tag" : "Fish:Swordfish Loin Portions",
            "weight" : 3,
            "lastInsert" : 1412597939124
        },
        {
            "tag" : "Vegetable:Carrots - alberto@gmail.com",
            "weight" : 2,
            "lastInsert" : 1412597939124
        }
    ]
},

{
    "_id" : ObjectId("542e67e07f724fc2af28ba75"),
    "id" : "",
    "email" : "alberto@gmail.com",
    "tags" : [
        {
            "tag" : "Paper Goods:Lialberto- Baking Cups",
            "weight" : 1,
            "lastInsert" : 1412327548205
        },
        {
            "tag" : "Fish:Swordfish Loin Portions",
            "weight" : 3,
            "lastInsert" : 1412597939124
        },
        {
            "tag" : "Vegetable:Carrots - alberto@gmail.com",
            "weight" : 2,
            "lastInsert" : 1412597939124
        }
    ]
}]

If my method is called with findUser(List("Fish:Swordfish Loin Portions", "Vegetable:Carrots - alberto@gmail.com")) my method had to returns the first User.

I know that is possible to do that with a cycle that check if a user had all the given tags, but it's too complicated and verbose. Exists an alternative??

How can I make that??

Community
  • 1
  • 1
alberto adami
  • 729
  • 1
  • 6
  • 25

1 Answers1

1

Use query like

db.test.find({$and:[{"tags.tag":"a"},{"tags.tag":"b"}]})

And you may simplify your life by using this reactivemongo-query https://github.com/sh1ng/ReactiveMongo-Queries

val cursor = collection.find(on[Interests].and(_.eq(_.tags.tag, "Fish:Swordfish Loin Portions"), _.eq(_.tags.tag, "Vegetable:Carrots - alberto@gmail.com"))).cursor[Interests]

Of course you may rewrite it in pure reactivemongo.

sh1ng
  • 2,808
  • 4
  • 24
  • 38