ใช้ Regular Expression + $not กรองเอกสารที่ไม่มีอักขระเฉพาะ
เมื่อต้องการหาเอกสารที่ฟิลด์ ไม่มี อักขระพิเศษ (เช่น #) ใช้ Regex แบบ Negative หรือ $not กับ Regex
ตัวอย่างข้อมูล
> db.regexDemo.insertOne({"CustomerId":"Customer#1234","CustomerName":"Chris"});
> db.regexDemo.insertOne({"CustomerId":"Customer5678","CustomerName":"Robert"});
> db.regexDemo.insertOne({"CustomerId":"Customer#777","CustomerName":"Carol"});
> db.regexDemo.insertOne({"CustomerId":"Customer777","CustomerName":"David"});
Case 1: Regex แบบ Negative Character Class ^[^#]*$
> db.regexDemo.find({CustomerId: /^[^#]*$/}).pretty();
ผลลัพธ์: ได้เฉพาะ CustomerId ที่ไม่มี #
{ "CustomerId" : "Customer5678", "CustomerName" : "Robert" }
{ "CustomerId" : "Customer777", "CustomerName" : "David" }
Case 2: ใช้ $not กับ Regex /#/
> db.regexDemo.find({CustomerId: {$not: /#/}}).pretty();
ผลลัพธ์: เหมือน Case 1
คำอธิบาย Regex
/^[^#]*$/: ^ = เริ่มต้น, [^#] = ไม่ใช่ #, * = 0 ตัวขึ้นไป, $ = สิ้นสุด → "ทั้งสตริงไม่มี #"/$not: /#//: ไม่ Match กับ Regex /#/ (คือ ไม่มี #)
ประสิทธิภาพ
- ทั้งสองวิธีไม่ใช้ Index ได้ (Full Collection Scan)
- หากคิวรีบ่อย ควรเพิ่มฟิลด์ Boolean เช่น
hasHash: true/falseตอน Insert แล้ว Index ฟิลด์นั้น $notกับ Regex ช้ากว่า Regex แบบ Negative Class เล็กน้อย
ขยาย: ข้ามหลายอักขระ
// ไม่มี # และ @
db.regexDemo.find({CustomerId: /^[^#@]*$/});
// ไม่มีตัวเลข
db.regexDemo.find({CustomerId: /^[^0-9]*$/});