Mongoose.js: Tìm người dùng theo tên người dùng Giá trị LIKE


94

Tôi muốn tìm một người dùng trong mongoDb bằng cách tìm kiếm một người dùng được gọi là giá trị. Vấn đề với:

username: 'peter'

là tôi không tìm thấy nó nếu tên người dùng là "Peter", hoặc "PeTER" .. hoặc đại loại như vậy.

Vì vậy, tôi muốn làm như sql

SELECT * FROM users WHERE username LIKE 'peter'

Hy vọng các bạn nhận được những gì tôi yêu cầu?

Ngắn gọn: 'giá trị trường LIKE' trong mongoose.js / mongodb


1
Chỉ cần một sang một bên, truy vấn SQL sẽ không tìm thấy Peterhoặc PeTERhoặc là LIKEkhông phải là case-insensitive.
beny 23

Câu trả lời:


143

Đối với những người đang tìm kiếm giải pháp thì đây là:

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

2
đối số "i" nghĩa là gì? Nó có liên quan gì đến phân biệt chữ hoa chữ thường không?
AzaFromKaza 19/09/13

2
"i" là đối số để chọn cờ tìm kiếm. "i" sau đó là phân biệt chữ hoa chữ thường. Bạn có thể đọc thêm về nó ở đây. developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
PeterBechP

10
Điều này giả sử regex không hợp lệ. Ví dụ: nếu bạn thêm "[" làm tên người dùng, sẽ ném ngoại lệ. Chỉ cần đảm bảo rằng bạn đang thử bắt hoặc nhập lại thông tin đầu vào của mình trước và kiểm tra [^ a-zA-Z0-9] rồi không tiếp tục. Trong trường hợp này, đầu vào chỉ kiểm tra của nó có ý nghĩa.
Jason Sebring

1
$ = Khớp phần cuối của chuỗi
PeterBechP

1
@JasonSebring Mặc dù tôi đồng ý rằng xác thực đầu vào không phải là một ý tưởng tồi, nhưng cách tiếp cận tốt nhất là một thuật toán thoát thực tế. Và ngoại lệ thậm chí không phải là vấn đề tồi tệ nhất, nhưng hãy tưởng tượng bạn đã sử dụng mã tương tự trên trang đăng nhập và một người dùng được nhập ".*"làm tên người dùng.
Tobias

79

Tôi đã gặp sự cố với điều này gần đây, tôi sử dụng mã này và hoạt động tốt đối với tôi.

var data = 'Peter';

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

Sử dụng trực tiếp /Peter/icông việc, nhưng tôi sử dụng '/'+data+'/i'và không làm việc cho tôi.


Chà, tôi vừa thử thêm một số nữa. Tôi xem nó cũng tìm nếu tôi chỉ viết P ?? hmmm.
PeterBechP

Có, tôi sử dụng cho các kiến ​​nghị ajax để tìm kiếm người dùng. Bạn có thể sửa đổi RegExp.
Donflopez

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

@MikeShi Ví dụ về tình huống này là gì?
Len Joseph

@LenJoseph nói chung là cuộc tấn công ReDoS: owasp.org/index.php/… , tôi không biết liệu mongoose có dễ bị tấn công vào thời điểm này hay không, hoặc liệu có bất kỳ chức năng dự định nào để phát hiện đầu vào ReDoS và khử trùng chúng ở cấp mongoose hay không.
Mike Shi

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

điều gì sẽ xảy ra nếu giá trị là một var? Làm thế nào để thiết lập điều đó? / varhere / i?
PeterBechP

2
@PeterBechP tạo một biểu thức chính quy: \new RegExp(var, "i")
Raynos

hoạt động tốt .. bây giờ tôi gặp sự cố .. Nó chỉ phải tìm peter nếu var là peter. Nhưng nếu tôi đặt var thành 'p', nó vẫn sẽ tìm thấy peter.
PeterBechP

@PeterBechP sau đó xóa cờ phân biệt chữ hoa chữ thường: \
Raynos

14
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);
    });

});  

13

Bạn nên sử dụng regex cho điều đó.

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

Tuy nhiên, hãy cảnh giác rằng truy vấn này không sử dụng chỉ mục.


9

mongoose doc để tìm. mongodb doc cho 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);
});

Lưu ý rằng đối số đầu tiên mà chúng tôi truyền cho mongoose.findOnehàm : { "name" : { $regex: /Ghost/, $options: 'i' } }, "name"là trường của tài liệu bạn đang tìm kiếm, "Ghost"là biểu thức chính quy, "i"là đối sánh không phân biệt chữ hoa chữ thường. Hy vọng điều này sẽ giúp bạn.


$ options là gì
kabuto178

8

Truy vấn sau sẽ tìm các tài liệu có chuỗi bắt buộc không in hoa chữ thường và xuất hiện trên toàn cầu

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

6

Đây là những gì tôi đang sử dụng.

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

5

Đây là mã của tôi với 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

nếu tôi muốn truy vấn tất cả bản ghi ở một số điều kiện , Tôi có thể sử dụng điều này:

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

Có vẻ như một cách sử dụng không cần thiết $regexkhi bạn có thể vừa mới sử dụng { $exists: true }.
sean

0

Chỉ bổ sung cho câu trả lời của @PeterBechP.

Đừng quên hiển thị các ký tự đặc biệt. 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

Đây là giải pháp của tôi để chuyển đổi mọi giá trị trong req.body thành 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 }) })
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.