Mongoose.js: ค้นหาผู้ใช้ด้วยค่าชื่อผู้ใช้ LIKE


95

ฉันต้องการค้นหาผู้ใช้ใน mongoDb โดยมองหาผู้ใช้ที่เรียกว่า value ปัญหาเกี่ยวกับ:

username: 'peter'

คือฉันไม่พบถ้าชื่อผู้ใช้คือ "Peter" หรือ "PeTER" .. หรืออะไรทำนองนั้น

ผมอยากทำเหมือน sql

SELECT * FROM users WHERE username LIKE 'peter'

หวังว่าพวกคุณจะได้รับสิ่งที่ฉันขอ?

ย่อ: 'ค่า LIKE ของฟิลด์' ใน mongoose.js / mongodb


1
เพียงกันแบบสอบถาม SQL จะไม่พบPeterหรือPeTERไม่ว่าจะเป็นLIKEไม่ได้เป็นกรณีตาย
beny23

คำตอบ:


148

สำหรับผู้ที่กำลังมองหาวิธีแก้ปัญหาอยู่ที่นี่:

var name = 'Peter';
model.findOne({name: new RegExp('^'+name+'$', "i")}, function(err, doc) {
  //Do your action here..
});

2
อาร์กิวเมนต์ "i" หมายถึงอะไร? มันมีอะไรเกี่ยวข้องกับ case sensitive หรือไม่?
AzaFromKaza

2
"i" คืออาร์กิวเมนต์สำหรับการเลือกแฟล็กการค้นหา จากนั้น "i" เป็นกรณีที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ คุณสามารถอ่านเพิ่มเติมได้ที่นี่ developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP

10
สิ่งนี้ถือว่า regex ไม่ถูกต้อง ตัวอย่างเช่นหากคุณเพิ่ม "[" เป็นชื่อผู้ใช้จะทำให้เกิดข้อยกเว้น เพียงตรวจสอบให้แน่ใจว่าคุณได้ลองจับหรือ regexing ข้อมูลที่คุณป้อนก่อนหน้านี้และตรวจสอบ [^ a-zA-Z0-9] จากนั้นไม่ดำเนินการต่อ ในกรณีนี้อินพุตทดสอบเป็นเพียงข้อมูลที่สมเหตุสมผล
Jason Sebring

1
$ = จับคู่ส่วนท้ายของสตริง
PeterBechP

1
@JasonSebring แม้ว่าฉันจะยอมรับว่าการตรวจสอบอินพุตไม่ใช่ความคิดที่ไม่ดี แต่แนวทางที่ดีที่สุดคืออัลกอริทึมการหลบหนีที่แท้จริง และข้อยกเว้นไม่ใช่ปัญหาที่เลวร้ายที่สุด แต่ลองนึกภาพคุณใช้รหัสที่คล้ายกันในหน้าเข้าสู่ระบบและผู้ใช้ป้อน".*"เป็นชื่อผู้ใช้
Tobias

78

ฉันมีปัญหากับสิ่งนี้เมื่อเร็ว ๆ นี้ฉันใช้รหัสนี้และทำงานได้ดีสำหรับฉัน

var data = 'Peter';

db.User.find({'name' : new RegExp(data, 'i')}, function(err, docs){
    cb(docs);
});

ใช้/Peter/iงานโดยตรงแต่ฉันใช้'/'+data+'/i'และไม่ได้ผลสำหรับฉัน


ฉันเพิ่งลองอีกครั้ง ฉันเห็นมันยังพบว่าฉันเขียน P ?? อืม
PeterBechP

ใช่ฉันใช้สำหรับคำร้อง ajax เพื่อค้นหาผู้ใช้ คุณสามารถแก้ไข RegExp
Donflopez

38
db.users.find( { 'username' : { '$regex' : req.body.keyWord, '$options' : 'i' } } )

@MikeShi สถานการณ์ตัวอย่างนี้คืออะไร?
Len Joseph

@LenJoseph โดยทั่วไปการโจมตี ReDoS: owasp.org/index.php/…ฉันไม่ทราบว่าพังพอนมีช่องโหว่หรือไม่หรือมีฟังก์ชันใด ๆ ที่ตั้งใจจะตรวจจับอินพุต ReDoS และฆ่าเชื้อในระดับพังพอน
Mike Shi

15
router.route('/product/name/:name')
.get(function(req, res) {

    var regex = new RegExp(req.params.name, "i")
    ,   query = { description: regex };

    Product.find(query, function(err, products) {
        if (err) {
            res.json(err);
        }

        res.json(products);
    });

});  

14
collection.findOne({
    username: /peter/i
}, function (err, user) {
    assert(/peter/i.test(user.username))
})

จะเกิดอะไรขึ้นถ้าค่าเป็น var? จะตั้งค่าได้อย่างไร? / varhere / i?
PeterBechP

2
@PeterBechP สร้างนิพจน์ทั่วไป: \new RegExp(var, "i")
Raynos

ใช้งานได้ดี .. ตอนนี้ฉันมีปัญหา .. มันต้องหาปีเตอร์เท่านั้นถ้า var เป็นปีเตอร์ แต่ถ้าฉันตั้งค่า var เป็น 'p' มันจะยังคงพบว่าปีเตอร์
PeterBechP

@PeterBechP แล้วลบแฟล็กความไม่ไวต่อเคส: \
Raynos

13

คุณควรใช้ regex สำหรับสิ่งนั้น

db.users.find({name: /peter/i});

อย่างไรก็ตามโปรดระวังว่าแบบสอบถามนี้ไม่ได้ใช้ดัชนี


9

mongoose doc สำหรับค้นหา mongodb doc สำหรับ regex

var Person = mongoose.model('Person', yourSchema);
// find each person with a name contains 'Ghost'
Person.findOne({ "name" : { $regex: /Ghost/, $options: 'i' } },
    function (err, person) {
             if (err) return handleError(err);
             console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation);
});

หมายเหตุอาร์กิวเมนต์แรกที่เราส่งผ่านไปยังmongoose.findOneฟังก์ชั่น{ "name" : { $regex: /Ghost/, $options: 'i' } }, "name"เป็นเขตของเอกสารที่คุณกำลังค้นหานั้น"Ghost"คือการแสดงออกปกติ"i"เป็นกรณีการจับคู่ตาย หวังว่านี่จะช่วยคุณได้


ตัวเลือก $ คืออะไร
kabuto178

8

แบบสอบถามต่อไปนี้จะค้นหาเอกสารที่มีตัวพิมพ์เล็กและใหญ่ที่ต้องการโดยไม่คำนึงถึงความสำคัญและมีเหตุการณ์ร่วมด้วย

var name = 'Peter';
    db.User.find({name:{
                         $regex: new RegExp(name, "ig")
                     }
                },function(err, doc) {
                                     //Your code here...
              });

6

นี่คือสิ่งที่ฉันใช้

module.exports.getBookByName = function(name,callback){
    var query = {
            name: {$regex : name}
    }
    User.find(query,callback);
}

5

นี่คือรหัสของฉันกับ expressJS:

router.route('/wordslike/:word')
    .get(function(request, response) {
            var word = request.params.word;       
            Word.find({'sentence' : new RegExp(word, 'i')}, function(err, words){
               if (err) {response.send(err);}
               response.json(words);
            });
         });

1

หากฉันต้องการสอบถามบันทึกทั้งหมดในบางเงื่อนไข, ฉันสามารถใช้สิ่งนี้:

if (userId == 'admin')
  userId = {'$regex': '.*.*'};
User.where('status', 1).where('creator', userId);

ดูเหมือนว่าไม่จำเป็นต้องใช้เมื่อคุณจะได้ใช้เพียงแค่$regex { $exists: true }
ฌอน

0

เพียงเติมเต็มคำตอบของ @PeterBechP

อย่าลืมสร้างตัวอักษรพิเศษ https://stackoverflow.com/a/6969486

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

var name = 'Peter+with+special+chars';

model.findOne({name: new RegExp('^'+escapeRegExp(name)+'$', "i")}, function(err, doc) {
  //Do your action here..
});

0

นี่คือคำตอบของฉันสำหรับการแปลงทุกค่าในreq.bodyเป็น mongoose LIKE param:

let superQ = {}

Object.entries({...req.body}).map((val, i, arr) => {
    superQ[val[0]] = { '$regex': val[1], '$options': 'i' }
})

User.find(superQ)
  .then(result => {
    res.send(result)})
  .catch(err => { 
    res.status(404).send({ msg: err }) })
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.