MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Cách hợp nhất trường mảng trong tài liệu trong tổng hợp Mongo

TLDR;

Các bản phát hành hiện đại nên sử dụng $reduce với $setUnion sau $group ban đầu như được hiển thị:

db.collection.aggregate([
  { "$group": {
    "_id": { "Host": "$Host", "ArtId": "$ArtId" },
    "count": { "$sum": 1 },
    "tags": { "$addToSet": "$tags" }
  }},
  { "$addFields": {
    "tags": {
      "$reduce": {
        "input": "$tags",
        "initialValue": [],
        "in": { "$setUnion": [ "$$value", "$$this" ] }
      }
    }
  }}
])

Bạn đã đúng khi tìm $addToSet nhưng khi làm việc với nội dung trong một mảng, bạn thường cần xử lý bằng $unwind Đầu tiên. Điều này "khử chuẩn hóa" các mục nhập mảng và về cơ bản tạo "bản sao" của tài liệu mẹ với mỗi mục nhập mảng là một giá trị số ít trong trường. Đó là những gì bạn cần để tránh hành vi mà bạn đang thấy nếu không sử dụng nó.

Mặc dù "số lượng" của bạn đặt ra một vấn đề thú vị, nhưng dễ dàng giải quyết thông qua việc sử dụng "thư giãn kép" sau $group ban đầu hoạt động:

db.collection.aggregate([
    // Group on the compound key and get the occurrences first
    { "$group": {
        "_id": { "Host": "$Host", "ArtId": "$ArtId" },
        "tcount": { "$sum": 1 },
        "ttags": { "$push": "$tags" }
    }},

    // Unwind twice because "ttags" is now an array of arrays
    { "$unwind": "$ttags" },
    { "$unwind": "$ttags" },

    // Now use $addToSet to get the distinct values        
    { "$group": {
        "_id": "$_id",
        "tcount": { "$first": "$tcount" },
        "tags": { "$addToSet": "$ttags" }
    }},

    // Optionally $project to get the fields out of the _id key
    { "$project": {
        "_id": 0,
        "Host": "$_id.Host",
        "ArtId": "$_id.ArtId",
        "count": "$tcount",
        "tags": "$ttags"
    }}
])

Bit cuối cùng với $project cũng ở đó bởi vì tôi đã sử dụng tên "tạm thời" cho từng trường trong các giai đoạn khác của quy trình tổng hợp. Điều này là do có sự tối ưu hóa trong $project "sao chép" các trường từ vùng hiện có theo thứ tự chúng đã xuất hiện "trước khi" bất kỳ trường "mới" nào được thêm vào tài liệu.

Nếu không, đầu ra sẽ giống như sau:

{  "count":2 , "tags":[ "tag1", "tag2", "tag3" ], "Host": "abc.com", "ArtId": "123" }

Trường hợp các trường không theo thứ tự như bạn nghĩ. Thực sự thì nhỏ nhặt, nhưng nó quan trọng đối với một số người, rất đáng để giải thích tại sao và cách xử lý.

Vì vậy, $unwind thực hiện công việc để giữ các mục được tách biệt và không nằm trong mảng và thực hiện $group đầu tiên cho phép bạn nhận "số lượng" các lần xuất hiện của khóa "nhóm".

$first toán tử được sử dụng sau đó "giữ" giá trị "đếm" đó, vì nó chỉ được "nhân đôi" cho mọi giá trị có trong mảng "thẻ". Dù sao thì tất cả đều có giá trị như nhau nên không thành vấn đề. Chỉ cần chọn một.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Lấy tên tháng từ một ngày trong SQL

  2. Cách kết nối cơ sở dữ liệu Mongo cục bộ với docker

  3. Node - Mongoose 3.6 - Sắp xếp truy vấn với trường phổ biến

  4. Làm cách nào để truy vấn các giá trị riêng biệt trong Mongoose?

  5. Quản lý nhiều công nghệ cơ sở dữ liệu với ClusterControl