Làm cách nào để khớp giá trị mảng trong MongoDB?

Tôi cần khớp tất cả các tài liệu trong đó mọi phần tử của một mảng khớp với một số vị từ. Điều đó có thể được thực hiện?

Câu trả lời

Vâng, truy vấn để làm điều này thực sự khá đơn giản để xây dựng

Hãy nhớ rằng khi bạn so khớp một mảng, MongoDB sẽ “tiếp cận bên trong” mảng để so sánh vị từ với mọi phần tử mảng đơn lẻ và trả về tài liệu nếu vị từ khớp với ít nhất một trong số chúng. Tôi muốn nói với những người mới sử dụng MongoDB rằng hãy nghĩ về mảng như một trường có thể chứa nhiều giá trị khác nhau cùng một lúc. Một khi bạn bắt đầu nghĩ về mảng theo cách đó, sẽ dễ hiểu hơn rất nhiều truy vấn như “trong đó A lớn hơn 50 VÀ A nhỏ hơn 10” không phải là vô nghĩa nếu “A” là một mảng, bởi vì các phần tử mảng khác nhau

Điều đó có nghĩa là để đảm bảo mọi phần tử mảng khớp với một số cấu trúc, bạn nên phủ định cấu trúc đó và sau đó phủ định lại truy vấn

Một ví dụ đơn giản có lẽ có thể giúp

Hãy tưởng tượng bạn có bộ tài liệu này

{ “a”: [ 1, 2, 3, 4 ] }
{ “a”: [ 3, 4, 5, 6 ] }
{ “a”: [ 5, 6, 7, 8 ] }
{ “a”: [ 1, 2, 3, 4, 5 ] }

Làm thế nào để bạn tìm thấy tất cả các tài liệu mà “a” nhỏ hơn 5?

{ “a”: [ 1, 2, 3, 4 ] }
{ “a”: [ 3, 4, 5, 6 ] }
{ “a”: [ 1, 2, 3, 4, 5 ] }

Điều này là do ít nhất một phần tử trong mỗi mảng này khớp với vị từ truy vấn của chúng tôi. Tài liệu thứ ba không có phần tử nào nhỏ hơn 5

Bây giờ chúng tôi chỉ muốn lấy lại các tài liệu có mọi phần tử khớp với cùng một vị từ. Một cách khác để nói “Tôi muốn mọi tài liệu có mỗi phần tử của mảng nhỏ hơn 5” sẽ là “Tôi muốn mọi tài liệu không có phần tử nào lớn hơn hoặc bằng 5”. Vì vậy, trước tiên chúng tôi phủ nhận truy vấn ban đầu của mình

db.coll.find({"a":{"$gte":5}})

và sau đó chúng tôi phủ nhận toàn bộ kết quả

db.coll.find({"$nor":[{"a":{"$gte":5}}]})

và như bạn mong đợi, kết quả là

{ “a”: [ 1, 2, 3, 4 ] }

Khi chúng ta xử lý các con số, thật dễ dàng để “phủ định” một điều kiện, nhưng với mảng, việc lập luận về “$not” và “$nor” có thể phức tạp, vì vậy, hãy thử lại với các chuỗi mà chúng ta không thể sử dụng “$gt” và

{ “a” : [ “1”, “2”, “3”, “4” ] }
{ “a” : [ “3”, “4”, “5”, “6” ] }
{ “a” : [ “5”, “6”, “7”, “8” ] }
{ “a” : [ “1”, “2”, “3”, “4”, “5” ] }

Hãy thử điều tương tự mà chúng tôi đã thử ở trên, trước tiên chúng tôi sẽ tìm kiếm một trong số các tập hợp “1”, “2”, “3”, “4” và bắt đầu từ đó

db.coll.find({“a”:{“$in”:[“1”,“2”,“3”,“4”]}})
{ “a” : [ “1”, “2”, “3”, “4” ] }
{ “a” : [ “3”, “4”, “5”, “6” ] }
{ “a” : [ “1”, “2”, “3”, “4”, “5” ] }
db.coll.find({“a”:{“$nin”:[“1”,“2”,“3”,“4”]}})
{ “a” : [ “5”, “6”, “7”, “8” ] }
Chuyện gì đã xảy ra? . Vậy làm cách nào để thể hiện truy vấn mà chúng tôi muốn tất cả các tài liệu có phần tử không nằm trong danh sách của chúng tôi?

Bất cứ khi nào câu hỏi (hoặc truy vấn) liên quan đến một phần tử của một mảng, thì rất có thể bạn nên sử dụng [“$elemMatch”][1] để diễn đạt nó. Thông thường, chúng tôi sử dụng “$elemMatch” để diễn đạt rằng chúng tôi muốn cùng một phần tử mảng khớp với nhiều điều kiện trong các vị từ truy vấn, nhưng cũng đúng khi sử dụng nó khi bạn đang cố gắng phủ định ý nghĩa của truy vấn bằng cách áp dụng phủ định cho

// find me all documents where at least one array element is *not* on our list
db.coll.find({"a":{"$elemMatch":{"$nin":["1","2","3","4"]}}})
{ "a" : [ "1", "2", "3", "4", "5" ] }
{ "a" : [ "3", "4", "5", "6" ] }
{ "a" : [ "5", "6", "7", "8" ] }
// now we negate the entire query
db.coll.find({"$nor":[{"a":{"$elemMatch":{"$nin":["1","2","3","4"]}}}]})
{ "a" : [ "1", "2", "3", "4" ] }

Đây là một ví dụ phức tạp khác liên quan đến một biểu thức chính quy - trong khi bạn có thể phủ định một biểu thức chính quy, bạn có thể vô tình giới hạn việc so khớp chỉ với các loại chuỗi và khi bạn có các mảng kiểu hỗn hợp (không được khuyến nghị, nhưng điều đó xảy ra) sẽ không mang lại cho bạn kết quả mong muốn

{ "a" : [ "str1", "str2", "str3", "notstr" ] }
{ "a" : [ "str1", "str2", "str3", "str4" ] }
{ "a" : [ 1, 2, 3, 4, 5 ] }
{ "a" : [ 5, 6, 7, 8, 9 ] }
{ "a" : [ "str1", 0, 10 ] }

Giả sử tôi chỉ muốn lấy lại các tài liệu có tất cả các phần tử “a” bắt đầu bằng các ký tự “str”. Hãy xem xét một số truy vấn và kết quả của chúng

db.coll.find({“a”:/^str/})
{ “a” : [ “str1”, “str2”, “str3”, “notstr” ] }
{ “a” : [ “str1”, “str2”, “str3”, “str4” ] }
{ “a” : [ “str1”, 0, 10 ] }
db.coll.find({“a”:{$not:/^str/}})
{ “a” : [ 1, 2, 3, 4, 5 ] }
{ “a” : [ 5, 6, 7, 8, 9 ] }
// negate regular expression:
db.coll.find({“a”:/^(?!str)/})
{ “a” : [ “str1”, “str2”, “str3”, “notstr” ] }
db.coll.find({“a”:{$not:/^(?!str)/}})
{ “a” : [ “str1”, “str2”, “str3”, “str4” ] }
{ “a” : [ 1, 2, 3, 4, 5 ] }
{ “a” : [ 5, 6, 7, 8, 9 ] }
{ “a” : [ “str1”, 0, 10 ] }

Có bất ngờ nào ở đây không? . Chúng tôi cũng thấy rằng “$not” được thêm vào bất kỳ truy vấn regex nào sẽ trả về phần bổ sung của các tài liệu được trả về mà không có “$not”. Đó không phải là những gì chúng ta cần khi cố gắng lấy tất cả các tài liệu với mọi phần tử thỏa mãn vị ngữ. Hãy xem liệu “$elemMatch” có mang đến cho chúng ta những gì chúng ta muốn không

{ “a”: [ 1, 2, 3, 4 ] }
{ “a”: [ 3, 4, 5, 6 ] }
{ “a”: [ 1, 2, 3, 4, 5 ] }
0

Bây giờ, hãy thử nó trên một cấu trúc tài liệu phức tạp hơn với một vị từ phức tạp hơn

{ “a”: [ 1, 2, 3, 4 ] }
{ “a”: [ 3, 4, 5, 6 ] }
{ “a”: [ 1, 2, 3, 4, 5 ] }
1

Nếu vị ngữ của chúng ta chỉ nói về “b. x” hoặc chỉ về “b. y”, chúng tôi sẽ sử dụng “$elemMatch” thay vì ký hiệu chấm để chạy truy vấn giống như ví dụ đầu tiên của chúng tôi. Để tìm tất cả các tài liệu trong đó “b. x” là 1, 2 hoặc 3, chúng ta có thể thực hiện các bước này (giả sử tất cả các truy vấn yêu cầu trong phép chiếu chỉ dành cho trường mà tôi đang truy vấn)

Làm cách nào để khớp các giá trị trong mảng trong MongoDB?

Toán tử $elemMatch so khớp các tài liệu chứa trường mảng với ít nhất một phần tử khớp với tất cả các tiêu chí truy vấn đã chỉ định . Nếu bạn chỉ xác định một điều kiện

Làm cách nào để so sánh các phần tử mảng trong MongoDB?

Bạn có thể sử dụng toán tử mảng tổng hợp như $filter hoặc $reduce để so sánh các phần tử mảng và trả về kết quả. Các toán tử mảng này hoạt động giống như các trình lặp (như lặp trong vòng lặp for trên trường mảng JavaScript hoặc Java).

Làm cách nào để tìm giá trị trong mảng đối tượng trong MongoDB?

Để tìm kiếm mảng đối tượng trong MongoDB, bạn có thể sử dụng toán tử $elemMatch . Toán tử này cho phép chúng ta tìm kiếm nhiều hơn một thành phần từ một đối tượng mảng.

Làm cách nào để lọc các phần tử mảng trong MongoDB?

Lọc phần tử mảng MongoDB Sử dụng toán tử $Filter . đầu vào - Điều này đại diện cho mảng mà chúng tôi muốn trích xuất. cond - Điều này đại diện cho tập hợp các điều kiện phải được đáp ứng. as – Trường tùy chọn này chứa tên cho biến đại diện cho từng phần tử của mảng đầu vào.

Làm cách nào để sử dụng mảng trong MongoDB?

Làm việc với mảng trong MongoDB .
Giới thiệu. .
Tạo và truy vấn tài liệu. .
Thêm một phần tử mảng. .
Cập nhật một phần tử mảng. .
Xóa một phần tử mảng. .
Thêm một Trường mới cho tất cả các Đối tượng trong Mảng. .
Cập nhật một phần tử mảng cụ thể dựa trên một điều kiện. .
Phần kết luận