Có thể thực hiện hợp nhất trong MongoDB theo kiểu 'SQL UNION' bằng cách sử dụng các tổng hợp cùng với tra cứu, trong một truy vấn duy nhất.
Một cái gì đó như thế này:
db.getCollection("AnyCollectionThatContainsAtLeastOneDocument").aggregate(
[
{ $limit: 1 }, // Reduce the result set to a single document.
{ $project: { _id: 1 } }, // Strip all fields except the Id.
{ $project: { _id: 0 } }, // Strip the id. The document is now empty.
// Lookup all collections to union together.
{ $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
{ $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
{ $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } },
// Merge the collections together.
{
$project:
{
Union: { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
}
},
{ $unwind: "$Union" }, // Unwind the union collection into a result set.
{ $replaceRoot: { newRoot: "$Union" } } // Replace the root to cleanup the resulting documents.
]);
Đây là giải thích về cách nó hoạt động:
-
Tạo một
aggregate
ra khỏi bất kỳ bộ sưu tập cơ sở dữ liệu của bạn có ít nhất một tài liệu trong đó. Nếu bạn không thể đảm bảo bất kỳ bộ sưu tập nào trong cơ sở dữ liệu của bạn sẽ không bị trống, bạn có thể giải quyết vấn đề này bằng cách tạo trong cơ sở dữ liệu của mình một số loại tập hợp 'giả' chứa một tài liệu trống duy nhất trong đó sẽ ở đó cụ thể để thực hiện các truy vấn liên hợp. -
Đặt giai đoạn đầu tiên của quy trình thành
{ $limit: 1 }
. Thao tác này sẽ loại bỏ tất cả các tài liệu của bộ sưu tập ngoại trừ tài liệu đầu tiên. -
Tách tất cả các trường của tài liệu còn lại bằng cách sử dụng
$project
giai đoạn:{ $project: { _id: 1 } }, { $project: { _id: 0 } }
-
Tổng hợp của bạn bây giờ chứa một tài liệu trống. Đã đến lúc thêm các tra cứu cho từng bộ sưu tập mà bạn muốn kết hợp với nhau. Bạn có thể sử dụng
pipeline
để thực hiện một số lọc cụ thể hoặc để lạilocalField
vàforeignField
là null để khớp với toàn bộ bộ sưu tập.{ $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } }, { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } }, { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
-
Bây giờ, bạn có một tập hợp chứa một tài liệu duy nhất chứa 3 mảng như sau:
{ Collection1: [...], Collection2: [...], Collection3: [...] }
Sau đó, bạn có thể hợp nhất chúng với nhau thành một mảng duy nhất bằng cách sử dụng
$project
cùng với$concatArrays
toán tử tổng hợp:{ "$project" : { "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] } } }
-
Bây giờ bạn có một tập hợp chứa một tài liệu duy nhất, trong đó có một mảng chứa liên hợp các tập hợp của bạn. Việc còn lại phải làm là thêm một
$unwind
và một$replaceRoot
giai đoạn để chia mảng của bạn thành các tài liệu riêng biệt:{ $unwind: "$Union" }, { $replaceRoot: { newRoot: "$Union" } }
-
Voilà. Bạn biết có một tập hợp kết quả chứa các tập hợp bạn muốn kết hợp với nhau. Sau đó, bạn có thể thêm các giai đoạn khác để lọc thêm, sắp xếp, áp dụng bỏ qua () và giới hạn (). Khá nhiều thứ bạn muốn.