Comment demander «n'est pas nul» à Mongo?

Réponses:

813

Cela renverra tous les documents avec une clé appelée "URL IMAGE", mais ils peuvent toujours avoir une valeur nulle.

db.mycollection.find({"IMAGE URL":{$exists:true}});

Cela renverra tous les documents avec à la fois une clé appelée "URL IMAGE" et une valeur non nulle.

db.mycollection.find({"IMAGE URL":{$ne:null}});

De plus, selon les documents, $ existe actuellement ne peut pas utiliser d'index, mais $ ne le peut.

Edit: Ajout de quelques exemples en raison de l'intérêt pour cette réponse

Compte tenu de ces inserts:

db.test.insert({"num":1, "check":"check value"});
db.test.insert({"num":2, "check":null});
db.test.insert({"num":3});

Cela renverra les trois documents:

db.test.find();

Cela renverra uniquement les premier et deuxième documents:

db.test.find({"check":{$exists:true}});

Cela ne retournera que le premier document:

db.test.find({"check":{$ne:null}});

Cela renverra uniquement les deuxième et troisième documents:

db.test.find({"check":null})
Tim Gautier
la source
13
Selon les documents, $ne inclut les documents qui ne contiennent pas le champ . Cela a-t-il changé depuis que vous avez publié la réponse? docs.mongodb.org/manual/reference/operator/query/ne
Andrew Mao
2
Je ne pense pas que cela ait changé. Lors de la vérification de $ ne, la valeur est vérifiée dans tous les documents, y compris ceux qui ne contiennent pas le champ, mais $ ne: null ne correspondra toujours pas à un document qui ne contient pas le champ puisque la valeur du champ est toujours nulle, même si le champ n'existe pas dans ce document.
Tim Gautier
2
Comment faites-vous simplement correspondre le deuxième document?
BT
1
@River J'ai vérifié quand j'ai écrit cela il y a 3 ans et, juste pour être sûr, je viens d'installer Mongo et de le réessayer. Cela fonctionne toujours de la même manière, la réponse est correcte. L'avant-dernière requête renvoie uniquement le 1er document.
Tim Gautier
1
Les exemples donnés rendent vraiment compréhensible comment l'utiliser. :-)
Eric Dela Cruz
92

Un liner est le meilleur:

db.mycollection.find({ 'fieldname' : { $exists: true, $ne: null } });

Ici,

mycollection : placez le nom de votre collection souhaitée

nomchamp : placez votre nom de champ désiré

Explication:

$ existe : Quand est vrai, $ existe correspond aux documents qui contiennent le champ, y compris les documents où la valeur du champ est nulle. Si est faux, la requête renvoie uniquement les documents qui ne contiennent pas le champ.

$ ne sélectionne les documents dont la valeur du champ n'est pas égale à la valeur spécifiée. Cela inclut les documents qui ne contiennent pas le champ.

Donc, dans votre cas fourni, la requête suivante qui va retourner tous les documents avec le champ imageurl existe et n'a pas de valeur nulle:

db.mycollection.find({ 'imageurl' : { $exists: true, $ne: null } });
Amitesh
la source
11
$exists: trueest redondant, $ne: nullsuffit.
Stanislav Karakhanov
Ce devrait être la meilleure réponse. $exists: truerenvoie nullégalement des valeurs. Il doit y avoir à la fois $exists: trueet $ne: null. Ce n'est PAS redondant.
Ismail Kattakath
47

Dans pymongo, vous pouvez utiliser:

db.mycollection.find({"IMAGE URL":{"$ne":None}});

Parce que pymongo représente mongo "null" comme python "None".

user2293072
la source
18
db.collection_name.find({"filed_name":{$exists:true}});

récupérer les documents qui contiennent ce nom_de_fichier même s'il est nul.

Ma proposition:

db.collection_name.find({"field_name":{$type:2}}) //type:2 == String

Vous pouvez vérifier le type d'attribut requis, il renverra tous les documents que son champ_nom interrogé contient une valeur parce que vous vérifiez sur le type du dossier sinon s'il est nul la condition de type ne correspond pas donc rien ne sera retourné.

Nb : si le champ_nom a une chaîne vide qui signifie "", il sera retourné. C'est le même comportement pour

db.collection_name.find({"filed_name":{$ne:null}});

Validation supplémentaire:

D'accord, nous n'avons donc pas encore terminé, nous avons besoin d'une condition supplémentaire.

db.collection_name.
find({ "field_name":{$type:2},$where:"this.field_name.length >0"})

OU

db.collection_name.
find({ "field_name":{$ne:null},$where:"this.field_name.length >0"})

Référence

Farouk El kholy
la source
14

Partage pour les futurs lecteurs.

Cette requête a fonctionné pour nous (requête exécutée à partir de la boussole MongoDB ):

{
  "fieldName": {
    "$nin": [
      "",
      null
    ]
  }
}
Mohammed Zameer
la source
1
{$ existe: vrai, $ ne: null} n'a pas montré de résultat correct. Votre requête fonctionne bien
Oleksandr Buchek
1
Attention, $ nin n'optimise pas souvent les index
Wheezil
4
db.<collectionName>.find({"IMAGE URL":{"$exists":"true"}, "IMAGE URL": {$ne: null}})
Berhanu Tarekegn
la source
Est-ce un document Json valide? Deux propriétés portant le même nom dans le document de requête. Je ne sais pas comment vous pourriez construire cela en mémoire si vous deviez.
BrentR
4

Dans un cas idéal, vous souhaitez tester les trois valeurs , null , "" ou vide (le champ n'existe pas dans l'enregistrement)

Vous pouvez effectuer les opérations suivantes.

db.users.find({$and: [{"name" : {$nin: ["", null]}}, {"name" : {$exists: true}}]})
Ankit Marothi
la source
3

Une alternative qui n'a pas été mentionnée, mais qui peut être une option plus efficace pour certains (ne fonctionnera pas avec les entrées NULL) est d'utiliser un index clairsemé (les entrées dans l'index n'existent que lorsqu'il y a quelque chose dans le champ). Voici un exemple d'ensemble de données:

db.foo.find()
{ "_id" : ObjectId("544540b31b5cf91c4893eb94"), "imageUrl" : "http://example.com/foo.jpg" }
{ "_id" : ObjectId("544540ba1b5cf91c4893eb95"), "imageUrl" : "http://example.com/bar.jpg" }
{ "_id" : ObjectId("544540c51b5cf91c4893eb96"), "imageUrl" : "http://example.com/foo.png" }
{ "_id" : ObjectId("544540c91b5cf91c4893eb97"), "imageUrl" : "http://example.com/bar.png" }
{ "_id" : ObjectId("544540ed1b5cf91c4893eb98"), "otherField" : 1 }
{ "_id" : ObjectId("544540f11b5cf91c4893eb99"), "otherField" : 2 }

Maintenant, créez l'index clairsemé sur le champ imageUrl:

db.foo.ensureIndex( { "imageUrl": 1 }, { sparse: true } )
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

Maintenant, il y a toujours une chance (et en particulier avec un petit ensemble de données comme mon échantillon) qu'au lieu d'utiliser un index, MongoDB utilise un scan de table, même pour une requête d'index couvert potentiel. Il s'avère que cela me donne un moyen facile d'illustrer la différence ici:

db.foo.find({}, {_id : 0, imageUrl : 1})
{ "imageUrl" : "http://example.com/foo.jpg" }
{ "imageUrl" : "http://example.com/bar.jpg" }
{ "imageUrl" : "http://example.com/foo.png" }
{ "imageUrl" : "http://example.com/bar.png" }
{  }
{  }

OK, donc les documents supplémentaires sans imageUrlsont retournés, juste vides, pas ce que nous voulions. Juste pour confirmer pourquoi, expliquez:

db.foo.find({}, {_id : 0, imageUrl : 1}).explain()
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 6,
    "nscannedObjects" : 6,
    "nscanned" : 6,
    "nscannedObjectsAllPlans" : 6,
    "nscannedAllPlans" : 6,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "server" : "localhost:31100",
    "filterSet" : false
}

Donc, oui, un BasicCursorest égal à un scan de table, il n'a pas utilisé l'index. Forçons la requête à utiliser notre index clairsemé avec hint():

db.foo.find({}, {_id : 0, imageUrl : 1}).hint({imageUrl : 1})
{ "imageUrl" : "http://example.com/bar.jpg" }
{ "imageUrl" : "http://example.com/bar.png" }
{ "imageUrl" : "http://example.com/foo.jpg" }
{ "imageUrl" : "http://example.com/foo.png" }

Et c'est le résultat que nous recherchions - seuls les documents avec le champ renseigné sont retournés. Cela utilise également uniquement l'index (c'est-à-dire qu'il s'agit d'une requête d'index couverte), donc seul l'index doit être en mémoire pour renvoyer les résultats.

Il s'agit d'un cas d'utilisation spécialisé et ne peut pas être utilisé généralement (voir les autres réponses pour ces options). En particulier, il convient de noter que dans l'état actuel des choses, vous ne pouvez pas utiliser count()de cette manière (pour mon exemple, il retournera 6 et non 4), veuillez donc utiliser uniquement lorsque cela est approprié.

Adam Comerford
la source
les champs de texte sont toujours des index clairsemés, vous n'avez pas besoin de le spécifier explicitement. juste mes 2 cents.
alianos
3

Le moyen le plus simple de vérifier l'existence de la colonne dans la boussole mongo est:

{ 'column_name': { $exists: true } }
Taha Hamedani
la source
1
Le problème avec cela est qu'il suppose que le champ n'a vraiment jamais été persisté, mais l'OP semble indiquer (à partir du titre) qu'il pourrait exister mais être défini explicitement sur null.
Carighan
-10

la requête sera

db.mycollection.find({"IMAGE URL":{"$exists":"true"}})

il renverra tous les documents ayant "URL IMAGE" comme clé ...........

Sagar Varpe
la source
1
@kilianc Ce n'est pas vrai. $ existe capturera également les valeurs nulles. Voir docs.mongodb.org/manual/reference/operator/query/exists
dorvak
@dorvak exactement, c'est pourquoi cela ne satisfera pas le cas d'utilisation de la question.
kilianc le
Cette réponse est fausse parce que $existsvérifie la clé "IMAGE URL"et ne prennent pas en compte la valeur de ce ( null) et se retourner un document "IMAGE URL" : null.
David Hariri