Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is possible use the operators "$ne" and "$elemMatch" in same query?

I'm trying to find all documents that tipo=CD and canciones does not contains subdocuments that has title=Pajaritos and cancion=2

This is what i like to achieve in canciones field:

not (title=Pajaritos and cancion=2)

I have the following collection:

{ 
    "tipo": "CD",
    "Artista":"Los piratas",
    "Titulo": "Recuerdos",
    "canciones": [
        {
            "cancion":1,
            "titulo":"Adios mi barco",
            "longitud": "3:20"
         },
         {
            "cancion":2,
            "titulo":"Pajaritos",
            "longitud": "4:15"
         }
     ]
},
{ 
    "tipo": "CD",
    "Artista":"Los piratas",
    "Titulo": "Recuerdos",
    "canciones": [
        {
            "cancion":1,
            "titulo":"Adios mi barco",
            "longitud": "3:20"
        },
        {
            "cancion":3,
            "titulo":"Pajaritos",
            "longitud": "4:15" 
        }
    ]
},

{ 
    "tipo": "CD",
    "Artista":"Los piratas",
    "Titulo": "Recuerdos",
    "canciones": [
        {
            "cancion":1,
            "titulo":"Adios mi barco",
            "longitud": "3:20"
        },
        {
            "cancion":3,
            "titulo":"Pajaritos",
            "longitud": "4:15" 
        },
        {
            "cancion":4,
            "titulo":"Pajaritos4",
            "longitud": "44:15" 
        }
 }

My query

db.media.find({"tipo" : "CD" ,"canciones" : { "$ne" : {"$elemMatch" :  {"titulo" : "Pajaritos", "cancion" : 2}}}})

My undesired results

{ "_id" : ObjectId("550f0a1c009ed3a1c9bbcdc1"), "tipo" : "CD", "Artista" : "Los piratas", "Titulo" : "Recuerdos", "canciones" : [ { "cancion" : 1, "titulo" : "Adios mi barco", "longitud" : "3:20" }, { "cancion" : 2, "titulo" : "Pajaritos", "longitud" : "4:15" } ] }
{ "_id" : ObjectId("550f0a1c009ed3a1c9bbcdc2"), "tipo" : "CD", "Artista" : "Los piratas", "Titulo" : "Recuerdos", "canciones" : [ { "cancion" : 1, "titulo" : "Adios mi barco", "longitud" : "3:20" }, { "cancion" : 3, "titulo" : "Pajaritos", "longitud" : "4:15" } ] }
{ "_id" : ObjectId("550f0a1c009ed3a1c9bbcdc3"), "tipo" : "CD", "Artista" : "Los piratas", "Titulo" : "Recuerdos", "canciones" : [ { "cancion" : 1, "titulo" : "Adios mi barco", "longitud" : "3:20" }, { "cancion" : 3, "titulo" : "Pajaritos", "longitud" : "4:15" }, { "cancion" : 4, "titulo" : "Pajaritos4", "longitud" : "44:15" } ] }

As you can see, the results contains "titulo" : "Pajaritos" which is trying to avoid.

Trying with $not operator instead of $ne

{ "_id" : ObjectId("550f173fc357b7a4e7a46e10"), "tipo" : "CD", "Artista" : "Los piratas", "Titulo" : "Recuerdos", "canciones" : [ { "cancion" : 1, "titulo" : "Adios mi barco", "longitud" : "3:20" }, { "cancion" : 3, "titulo" : "Pajaritos", "longitud" : "4:15" } ] }
{ "_id" : ObjectId("550f173fc357b7a4e7a46e11"), "tipo" : "CD", "Artista" : "Los piratas", "Titulo" : "Recuerdos", "canciones" : [ { "cancion" : 1, "titulo" : "Adios mi barco", "longitud" : "3:20" }, { "cancion" : 3, "titulo" : "Pajaritos", "longitud" : "4:15" }, { "cancion" : 4, "titulo" : "Pajaritos4", "longitud" : "44:15" } ] }
like image 495
Ricardo Avatar asked Mar 22 '15 19:03

Ricardo


People also ask

What is the difference between the $all operator and the $in operator?

$all operator retrieves all the documents which contains the subset of the values we pass. The subset might be in any order. $in operator retrieves all the documents which contains the either of the values we pass. db.

What does $elemMatch do in MongoDB?

Definition. The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.

How do I query an array of objects in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

How do I match an array in MongoDB?

Use $match With $all to Find Matching Documents in an Array in MongoDB. The $all is equivalent to the $and operator. This code retrieves all those documents where the courses array contains all the specified elements for the $all operator. The resulting documents must contain Java and Python elements.


1 Answers

In order to get the expected results, I would use the $not operator instead of the $ne operator. The $not operator would pretty match negate $elemMatch and give you the expected results. Your query shall therefore be:

db.media.find({
    "tipo": "CD",
    "canciones": {
        "$not": {
            "$elemMatch": {
                "titulo": "Pajaritos",
                "cancion": 2
            }
        }
    }
})

I hope it helps.

like image 131
manu2013 Avatar answered Oct 11 '22 05:10

manu2013