การเปรียบเทียบพังพอน _id และสตริง


197

ฉันมีแอปพลิเคชั่น node.js ที่ดึงข้อมูลบางส่วนและติดเข้าไปในวัตถุเช่นนี้

var results = new Object();

User.findOne(query, function(err, u) {
    results.userId = u._id;
}

เมื่อฉันทำ if / then ตาม ID ที่เก็บไว้นั้นการเปรียบเทียบจะไม่เป็นจริง:

if (results.userId == AnotherMongoDocument._id) {
    console.log('This is never true');
}

เมื่อฉันทำ console.log ของทั้งสอง id พวกเขาตรงกับ:

User id: 4fc67871349bb7bf6a000002 AnotherMongoDocument id: 4fc67871349bb7bf6a000002

ฉันสมมติว่านี่เป็นปัญหาประเภทข้อมูลบางอย่าง แต่ฉันไม่แน่ใจว่าจะแปลง results.userId เป็นประเภทข้อมูลที่จะส่งผลให้การเปรียบเทียบข้างต้นเป็นจริงและสมองที่ได้รับการว่าจ้างจากภายนอก (aka Google) ไม่สามารถช่วยได้

คำตอบ:


361

Mongoose ใช้ไดรเวอร์ mongodb-native ซึ่งใช้ชนิด ObjectID ที่กำหนดเอง คุณสามารถเปรียบเทียบ ObjectID กับ.equals()วิธีการ results.userId.equals(AnotherMongoDocument._id)ด้วยตัวอย่างของคุณ ประเภท ObjectID ยังมีtoString()วิธีการหากคุณต้องการจัดเก็บ ObjectID รุ่นที่เป็นสตริงในรูปแบบ JSON หรือคุกกี้

หากคุณใช้ObjectID = require("mongodb").ObjectID(ต้องใช้ไลบรารี mongodb-native) คุณสามารถตรวจสอบว่าresults.userIdเป็นตัวระบุที่ถูกต้องด้วยresults.userId instanceof ObjectIDหรือไม่

เป็นต้น


13
เอกสารสำหรับ.equals(): mongodb.github.io/node-mongodb-native/api-bson-generated/…
Anthony Panozzo

4
หากคุณกำลังใช้งานอยู่mongooseคุณสามารถrequire('mongoose').mongo.ObjectIDทำได้โดยไม่ต้องแสดงรายการการพึ่งพาเพิ่มเติมใด ๆ
JoshuaDavid

63

ObjectIDs คือวัตถุดังนั้นหากคุณเพิ่งเปรียบเทียบพวกเขากับ==คุณกำลังเปรียบเทียบการอ้างอิงของพวกเขา หากคุณต้องการเปรียบเทียบค่าของพวกเขาคุณต้องใช้ObjectID.equalsวิธีการ:

if (results.userId.equals(AnotherMongoDocument._id)) {
    ...
}


8

คำตอบที่ยอมรับนั้น จำกัด สิ่งที่คุณสามารถทำได้กับรหัสของคุณ ตัวอย่างเช่นคุณจะไม่สามารถค้นหาอาร์เรย์Object Idsโดยใช้วิธีเท่ากับ แต่จะเหมาะสมกว่าที่จะใช้สตริงและเปรียบเทียบคีย์เสมอ

นี่คือคำตอบตัวอย่างในกรณีที่คุณจำเป็นต้องใช้indexOf()เพื่อตรวจสอบภายในอาร์เรย์ของการอ้างอิงสำหรับรหัสเฉพาะ สมมติว่าqueryเป็นแบบสอบถามที่คุณกำลังดำเนินการสมมติว่าsomeModelเป็นรุ่น mongo สำหรับรหัสที่คุณกำลังมองหาและในที่สุดก็ถือว่าresults.idListเป็นเขตข้อมูลที่คุณกำลังมองหา ID วัตถุของคุณมา

query.exec(function(err,results){
   var array = results.idList.map(function(v){ return v.toString(); });
   var exists = array.indexOf(someModel._id.toString()) >= 0;
   console.log(exists);
});

1
หรือสายการบินlet exists = results.idList.filter(val => val.toString() === thisIsTheStringifiedIdWeAreLookingFor).length ? true : false
Zlatko

4
@Zlatko ฉันไม่ใช่แฟนตัวยงของซินแท็กซ์ใหม่
r3wt

2
@Zlatko const exists = results.idList.some(val => val.toString() === thisIsTheStringifiedIdWeAreLookingFor) หรือ const exists = results.idList.some(val => val.equals(someModel._id))
axanpi

1
@Zlatko ทุกปีต่อมาและคาดเดาสิ่งที่ ฉันต้องการเวอร์ชันของคุณที่จะระเบิดในขณะนี้ ถ้าฉันเพิ่มลงในคำตอบของฉันด้วยการระบุแหล่งที่มาที่เหมาะสม
r3wt

1
ราคาของความคืบหน้า :) แน่นอนคุณสามารถใช้คำตอบมันมีวัตถุประสงค์เพื่อให้ทางเลือกหรือความช่วยเหลือถ้าเป็นไปได้
Zlatko


0

ฉันประสบปัญหาเดียวกันและฉันก็แก้ไขปัญหาด้วยความช่วยเหลือJSON.stringify()ดังนี้: -

if (JSON.stringify(results.userId) === JSON.stringify(AnotherMongoDocument._id)) {
        console.log('This is never true');
}

0

วิธีแก้ปัญหาที่เป็นไปได้สามข้อที่แนะนำที่นี่มีกรณีการใช้งานที่แตกต่างกัน

  1. ใช้. เท่ากับเมื่อเปรียบเทียบ ObjectID กับ mongoDocuments สองรายการนี้

    results.userId.equals (AnotherMongoDocument._id)

  2. ใช้. toString () เมื่อเปรียบเทียบการแทนค่าสตริงของ ObjectID กับ ObjectID ของ mongoDocument แบบนี้

    results.userId === AnotherMongoDocument._id.toString ()


ทางออกที่สามที่เป็นไปได้คืออะไร?
Chris Catignani
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.