Kết hợp AND và OR để làm filter trong mongodb



  • Đây là dữ liệu của mình:
    {
    "telephone" : "0123456789",
    "isActive" : false
    }

    Mình đang làm cái filter ngoài màn hình gồm có tìm theo số đt và tìm theo trạng thái active hay chưa. Trạng thái gồm có 3 giá trị: true, false và rỗng(tìm cả 2 trạng thái true và false luôn).

    Trường hợp 1: Thực hiện riêng lẽ từng điều kiện

    • Tìm tất cả:
      db.customers.find({$or:[{"telephone": ""},{"":""}]})
    • Tìm theo giá trị nhập vào:
      db.customers.find({$or:[{"telephone": "0123456789"},{"0123456789":"0123456789"}]})
      Tương tự với cái active

    Trường hợp 2: Khi mình kết hợp với câu điều kiện AND

    • Tìm tất cả:
      db.customers.find({
      $and:[
      {$or:[{"isActive": ""},{"" : ""}]},
      {$or:[{"telephone": ""},{"":""}]}
      ]})
      Cái này nó chạy đúng
    • Lấy tất cả trạng thái nhưng nhập vào số đt:
      db.customers.find({
      $and:[
      {$or:[{"isActive": ''},{'' : ''}]},
      {$or:[{"telephone": "0123456789"},{"0123456789":"0123456789"}]}
      ]})
      Cái này chạy thì nó cứ lấy lên hết luôn, mặc dù mình sử dụng AND
      Theo mình hiểu thì nó lấy điều kiện telephone và tất cả trạng thái mà sao nó chạy không đúng, có ai có cách viết nào hay không góp ý mình với


  • Thực sự đọc vấn đề bạn trình bày, tôi không hiểu bạn xây dựng query csdl ra sao nữa.
    Trường hợp 1 : Bạn muốn tìm toàn bộ record không có số phone hoặc tìm toàn bộ ? toàn bộ record chăng hay toàn bộ có số phone . Vì query ({$or:[{"telephone": ""},{"":""}] rõ ràng nó là thế.
    Query {$or:[{"telephone": "0123456789"},{"0123456789":"0123456789"}]} không biết là tôi sai hay không mà lại có field 0123456789 ở đây , bạn dùng số phone làm field cho mỗi bản ghi. Omg :D
    Trường hợp 2
    theo như
    { "telephone" : "0123456789", "isActive" : false }
    => Một số phone chỉ ứng với một isActive. Dùng {$or:[{"isActive": ''},{'' : ''}]},{$or:[{"telephone": "0123456789"},{"0123456789":"0123456789"}]} quá là lãng phí, khả năng mongoDB quét toàn bộ bản ghi cho một số phone cụ thể !
    Tôi không test đoạn này vì rối quá, không thể hiểu ý luôn. Đề nghị các cao nhân khác giúp bạn này.
    Muốn giúp nhiều bạn trên forum mà nhiều lúc đọc chả hiểu cái vấn đề nó là gì luôn.



  • Ở trường hợp 1: Nếu người dùng nhập vào số đt thì mình chỉ lấy số đt đó ra thôi, còn nếu không nhập gì cả tức là lấy toàn bộ. Chứ ko phải dùng số phone làm field cho mỗi bản ghi đâu T_T. Tại mình viết theo kiểu đó thì thấy nó chạy được mà thấy cũng hơi kỳ kỳ nên đi hỏi.
    Trường hợp 2: Do thấy trường hợp 1 chạy theo kiểu đó đúng nên mình mới bê cái đó xuống áp dụng vào thêm với cột isActive. Trường hợp này người dùng kết hợp 2 điều kiện tìm theo số đt và tìm theo trạng thái

    PS: Nếu viết trong SQL Server thì mình viết vậy
    WHERE (telephone = @telephone OR @telephone = '')
    AND (isActive = @isActive OR @isActive = '')

    Thêm cái hình cho dễ hình dung 0_1472089394008_Untitled.png



  • Bạn không nên xử lý qua mongodb, nên xử lý check not null ở tầng trên NodeJS, đồng thời nên dùng regex vì như vậy sẽ tra cứu được thông tin đc dễ dàng hơn, ví dụ:
    var query = {};
    if(telephone != ' '){
    query.telephone = {'$regex': telephone};
    }
    if(isActive != ' '){
    query.isActive = isActive;
    }
    db.collection('customers').find(query, options);



  • Cám ơn bạn, mình cũng nghĩ tới việc xử lý truy vấn trên nodejs nhưng muốn biết dưới mongodb có cách nào hay không ^^


Log in to reply