J'essaye de comparer req.user._id avec un tableau d'ObjectIds renvoyé par une requête MongoDB. Mais toutes les vérifications d'égalité .includes(), strictes et lâches ont échoué.

Voici la logique de mon contrôleur (tronquée pour plus de simplicité):

// Get the ID of the document from the request
const someDocId = req.body.id;

// Perform the search with projection
const result = await Some_DB.findById(someDocId,{adminIds:1, _id:0}).lean();

/*
The structure of the query result is as the following:
{
  adminIds: [ 5f77ba7d1a0fba8f5e811e76, 6035f2e7174d4961808944d1 ],
}

And req.user._id is equal to 6035f2e7174d4961808944d1
*/

// When I do
console.log(result.adminIds[1] === req.user._id);
console.log(result.adminIds[1] == req.user._id);
console.log(result.adminIds.includes(req.user._id))

// I also tried
const { ObjectId, } = require('mongoose').Types
console.log(result.adminIds[1] === ObjectId(req.user._id));
console.log(result.adminIds[1] == ObjectId(req.user._id));
console.log(result.adminIds.includes(ObjectId(req.user._id)))

// The result is always false


// Additional Info: 
(the results below are the same with or without .lean()

const { ObjectId, } = require('mongoose').Types
const a = sphereInfo.adminIds[1];
const b = req.user._id; 
console.log(a instanceof ObjectId); // => true
console.log(b instanceof ObjectId); // => true

console.log(typeof(result.adminIds[1])); // => object
console.log(typeof(req.user._id)); // => object

console.log(result.adminIds[1]); 
// 6035f2e7174d4961808944d1 (note:there is no single quote around)
console.log(req.user._id); 
// 6035f2e7174d4961808944d1 (note:there is no single quote around)


const a = Object.values(sphereInfo.adminIds[1]);
const b = Object.values(req.user._id);
console.log(a); // => [ 'ObjectID', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
console.log(b); // => [ 'ObjectID', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]

const a = Object.getOwnPropertyNames(sphereInfo.adminIds[1]);
const b = Object.getOwnPropertyNames(req.user._id);
console.log(a); // => [ '_bsontype', 'id' ]
console.log(b); // => [ '_bsontype', 'id' ]

console.log(Object.entries(sphereInfo.adminIds[1]));
console.log(Object.entries(req.user._id));
/*
Result:
[
  [ '_bsontype', 'ObjectID' ],
  [ 'id', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
]
[
  [ '_bsontype', 'ObjectID' ],
  [ 'id', <Buffer 60 35 f2 e7 17 4d 49 61 80 89 44 d1> ]
]
*/

console.log(JSON.stringify(sphereInfo.adminIds[1]));
console.log(JSON.stringify(req.user._id));
/*
Result:
"6035f2e7174d4961808944d1"
"6035f2e7174d4961808944d1"
*/

// After removing .lean()
console.log(result.adminIds[1] === req.user._id); // => false
console.log(result.adminIds[1] == req.user._id); // => false
console.log(result.adminIds.includes(req.user._id)) // => true

Le schéma (tronqué pour simplifier):

// Dependencies
const mongoose = require('mongoose');

const Schema = mongoose.Schema;

// Create Schema
const SomeSchema = new Schema({

    adminIds: [{
        type: Schema.Types.ObjectId,
        ref: 'user',
    }],

}, {
    collection: 'SomeCollection',
    timestamps: true,
});

module.exports = { SomeSchema, };
.includes() .lean() .lean() .inclides()

Selon le Doc. Mongoose:

L'option lean indique à Mongoose de ne pas hydrater les documents de résultat. Cela rend les requêtes plus rapides et moins gourmandes en mémoire, mais les documents résultants sont de simples objets JavaScript (POJO), pas des documents Mongoose. Par défaut, les requêtes Mongoose retournent une instance de la classe Mongoose Document. Les documents sont beaucoup plus lourds que les objets JavaScript vanille car ils ont beaucoup d'état interne pour le suivi des modifications. L'activation de l'option lean indique à Mongoose de ne pas instancier un document Mongoose complet et de vous donner simplement le POJO.

Le document a également mentionné que l'inconvénient de l'activation du lean est que les documents lean n'ont pas:

  • Suivi des modifications
  • Casting et validation
  • Getters et setters
  • Virtuels
  • enregistrer()
.lean() .includes() .lean() .includes .lean()
1
Aviv Lo 24 févr. 2021 à 21:42

3 réponses

Meilleure réponse

La différence est subtile, mais elle existe. Avec .lean(), votre requête se résout finalement avec un tableau dans result.adminIds; la mise en garde est que chaque élément de ce tableau est ObjectId - qui, comme @codemonkey l'a correctement mentionné, reste ObjectId - un objet. Et lorsque vous essayez de trouver un ObjectId particulier dans ce tableau avec includes, la recherche doit simplement échouer en raison de la non-égalité des références.

Cependant, lorsque la requête est exécutée telle quelle, sans .lean () appliqué, result.adminIds n'est plus simplement un tableau - c'est MongooseArray qui a beaucoup de méthodes de tableau écrasées. Et c'est ainsi que Mongoindexprot (qui est utilisé dans

raina77ow 24 févr. 2021 à 20:50

Je ne sais pas exactement pourquoi la documentation insiste sur le fait qu'il s'agit de POJO, mais les résultats que vous obtenez correspondent à objets MongoDB ObjectID. Peut-être disent-ils qu'ils sont des POJO parce qu'ils ne sont pas construits par leurs constructeurs pertinents et qu'ils ne sont que des propriétés transmises à un nouvel objet.

Vous souhaitez comparer la propriété str si vous souhaitez comparer la valeur hexadécimale que vous voyez sur votre console.

console.log(result.adminIds[1].str === req.user._id.str);

Sinon, vous comparez deux objets différents (ce qui est toujours faux).

La seule façon dont cela vérifierait vrai:

console.log(result.adminIds[1] === req.user._id);

Ce serait le cas s'ils sont tous les deux le même objet ou s'ils sont tous les deux la même chaîne.

À mon avis

Je n'appellerais pas un objet qui étend valueOf et / ou toString un POJO car il étend essentiellement CERTAINES fonctionnalités d'objets JS. Par conséquent, ce n'est plus clair.

1
MinusFour 24 févr. 2021 à 20:18

lean() renverra des POJO, mais les valeurs ObjectId seront toujours de type Object. Les résultats de votre propre test confirment que:

console.log(typeof(result.adminIds[1])); // => object
console.log(typeof(req.user._id)); // => object

En tant que tel, pour comparer ces deux valeurs, il vous suffit de comparer comme suit:

console.log(result.adminIds[1].toString() === req.user._id.toString());

Au moins c'est ce que je fais toujours et ça marche toujours.

1
codemonkey 24 févr. 2021 à 19:23