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

Tổng mảng lồng nhau trong node.js mongodb

Hãy bắt đầu với tuyên bố từ chối trách nhiệm cơ bản trong đó phần nội dung chính của câu trả lời mà vấn đề đã được giải đáp tại đây tại Tìm trong Mảng đôi lồng nhau MongoDB . Và "để ghi lại" Double cũng áp dụng cho Triple hoặc Quadrupal hoặc BẤT KỲ mức độ lồng vào nhau về cơ bản là cùng một nguyên tắc LUÔN .

Điểm chính khác của bất kỳ câu trả lời nào cũng là Don't NEST Arrays , vì như đã được giải thích trong câu trả lời đó (và tôi đã lặp lại điều này nhiều lần), bất kỳ lý do gì bạn "nghĩ" bạn có cho "lồng vào nhau" thực sự không mang lại cho bạn những lợi thế mà bạn đạt được nó sẽ có. Trên thực tế, "làm tổ" thực sự chỉ khiến cuộc sống trở nên khó khăn hơn nhiều.

Các vấn đề lồng ghép

Quan niệm sai lầm chính về bất kỳ bản dịch nào của cấu trúc dữ liệu từ mô hình "quan hệ" chỉ luôn được hiểu là "thêm cấp mảng lồng nhau" cho mỗi và mọi mô hình liên quan. Những gì bạn đang trình bày ở đây không phải là ngoại lệ đối với quan niệm sai lầm này vì nó rất có vẻ được "bình thường hóa" để mỗi mảng con chứa các mục liên quan đến mảng chính của nó.

MongoDB là một cơ sở dữ liệu dựa trên "tài liệu", vì vậy nó cho phép bạn thực hiện điều này hoặc trên thực tế là bất kỳ nội dung cấu trúc dữ liệu nào mà bạn muốn. Tuy nhiên, điều đó không có nghĩa là dữ liệu ở dạng như vậy dễ sử dụng hoặc thực sự thiết thực cho mục đích thực tế.

Hãy điền vào lược đồ với một số dữ liệu thực tế để chứng minh:

{
  "_id": 1,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-01"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-02"),
                  "quantity": 1
                },
              ]
            },
            { 
              "third_item": "B",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
              ]
            }
          ]
        },
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "B",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
              ]
            }
          ]
        }
      ]
    },
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "B",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
              ]
            }
          ]
        }
      ]
    }
  ]
},
{
  "_id": 2,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "A",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 2,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-10-31"),
                  "quantity": 1
                },
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
},
{
  "_id": 3,
  "first_level": [
    {
      "first_item": "A",
      "second_level": [
        {
          "second_item": "B",
          "third_level": [
            { 
              "third_item": "A",
              "forth_level": [
                { 
                  "price": 1,
                  "sales_date": new Date("2018-11-03"),
                  "quantity": 1
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Điều đó hơi khác một chút so với cấu trúc trong câu hỏi nhưng đối với mục đích minh họa, nó có những thứ chúng ta cần xem xét. Chủ yếu có một mảng trong tài liệu có các mục với một mảng con, đến lượt nó có các mục trong một mảng con, v.v. "bình thường hóa" tất nhiên ở đây là bởi các số nhận dạng trên mỗi "cấp độ" như một "loại mặt hàng" hoặc bất kỳ thứ gì bạn thực sự có.

Vấn đề cốt lõi là bạn chỉ muốn "một số" dữ liệu từ bên trong các mảng lồng nhau này và MongoDB thực sự chỉ muốn trả lại "tài liệu", có nghĩa là bạn cần thực hiện một số thao tác để truy cập vào những "con" phù hợp đó mặt hàng ".

Ngay cả về vấn đề "chính xác" việc chọn tài liệu phù hợp với tất cả các "tiêu chí phụ" này yêu cầu sử dụng rộng rãi $ elemMatch để có được sự kết hợp chính xác của các điều kiện trên mỗi cấp độ của các phần tử mảng. Bạn không thể sử dụng trực tiếp "Ký hiệu dấu chấm" do nhu cầu về những nhiều điều kiện . Không có $ elemMatch câu lệnh mà bạn không nhận được "kết hợp" chính xác và chỉ nhận được tài liệu trong đó điều kiện là đúng trên bất kỳ phần tử mảng.

Đối với thực tế "lọc ra nội dung mảng" thì đó thực sự là một phần của sự khác biệt bổ sung:

db.collection.aggregate([
  { "$match": {
    "first_level": {
      "$elemMatch": {
        "first_item": "A",
        "second_level": {
          "$elemMatch": {
            "second_item": "A",
            "third_level": {
              "$elemMatch": {
                "third_item": "A",
                "forth_level": {
                  "$elemMatch": {
                    "sales_date": {
                      "$gte": new Date("2018-11-01"),
                      "$lt": new Date("2018-12-01")
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }},
  { "$addFields": {
    "first_level": {
      "$filter": {
        "input": {
          "$map": {
            "input": "$first_level",
            "in": {
              "first_item": "$$this.first_item",
              "second_level": {
                "$filter": {
                  "input": {
                    "$map": {
                      "input": "$$this.second_level",
                      "in": {
                        "second_item": "$$this.second_item",
                        "third_level": {
                          "$filter": {
                            "input": {
                              "$map": {
                                "input": "$$this.third_level",
                                 "in": {
                                   "third_item": "$$this.third_item",
                                   "forth_level": {
                                     "$filter": {
                                       "input": "$$this.forth_level",
                                       "cond": {
                                         "$and": [
                                           { "$gte": [ "$$this.sales_date", new Date("2018-11-01") ] },
                                           { "$lt": [ "$$this.sales_date", new Date("2018-12-01") ] }
                                         ]
                                       }
                                     }
                                   }
                                 } 
                              }
                            },
                            "cond": {
                              "$and": [
                                { "$eq": [ "$$this.third_item", "A" ] },
                                { "$gt": [ { "$size": "$$this.forth_level" }, 0 ] }
                              ]
                            }
                          }
                        }
                      }
                    }
                  },
                  "cond": {
                    "$and": [
                      { "$eq": [ "$$this.second_item", "A" ] },
                      { "$gt": [ { "$size": "$$this.third_level" }, 0 ] }
                    ]
                  }
                }
              }
            }
          }
        },
        "cond": {
          "$and": [
            { "$eq": [ "$$this.first_item", "A" ] },
            { "$gt": [ { "$size": "$$this.second_level" }, 0 ] }
          ]
        } 
      }
    }
  }},
  { "$unwind": "$first_level" },
  { "$unwind": "$first_level.second_level" },
  { "$unwind": "$first_level.second_level.third_level" },
  { "$unwind": "$first_level.second_level.third_level.forth_level" },
  { "$group": {
    "_id": {
      "date": "$first_level.second_level.third_level.forth_level.sales_date",
      "price": "$first_level.second_level.third_level.forth_level.price",
    },
    "quantity_sold": {
      "$avg": "$first_level.second_level.third_level.forth_level.quantity"
    } 
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quanity_sold": "$quantity_sold"
      }
    },
    "quanity_sold": { "$avg": "$quantity_sold" }
  }}
])

Điều này được mô tả tốt nhất là "lộn xộn" và "liên quan". Không chỉ là truy vấn ban đầu của chúng tôi để lựa chọn tài liệu với $ elemMatch nhiều hơn một chút, nhưng sau đó chúng tôi có bộ lọc $ tiếp theo $ map xử lý cho mọi cấp độ mảng. Như đã đề cập trước đó, đây là mô hình bất kể thực tế có bao nhiêu cấp.

Bạn có thể luân phiên thực hiện $ unwind $ match kết hợp thay vì lọc các mảng tại chỗ, nhưng điều này gây ra thêm chi phí cho $ thư giãn trước khi nội dung không mong muốn bị xóa, vì vậy, trong các bản phát hành hiện đại của MongoDB, thông thường tốt hơn là $ filter từ mảng đầu tiên.

Nơi cuối cùng ở đây là bạn muốn $ group bởi các phần tử thực sự bên trong mảng, vì vậy, cuối cùng bạn cần $ unwind từng cấp của các mảng trước đây.

Sau đó, "phân nhóm" thực tế thường đơn giản bằng cách sử dụng sales_date giá thuộc tính cho đầu tiên tích lũy và sau đó thêm giai đoạn tiếp theo vào $ push giá khác nhau giá trị bạn muốn tích lũy trung bình trong mỗi ngày dưới dạng giây tích lũy.

LƯU Ý :Cách xử lý thực tế của ngày tháng cũng có thể khác nhau trong thực tế sử dụng tùy thuộc vào mức độ chi tiết mà bạn lưu trữ chúng. Trong mẫu này, tất cả các ngày đều đã được làm tròn đến đầu mỗi "ngày". Nếu bạn thực sự cần tích lũy các giá trị "datetime" thực, thì bạn có thể thực sự muốn một cấu trúc như thế này hoặc tương tự:

{ "$group": {
  "_id": {
    "date": {
      "$dateFromParts": {
        "year": { "$year": "$first_level.second_level.third_level.forth_level.sales_date" },
        "month": { "$month": "$first_level.second_level.third_level.forth_level.sales_date" },
        "day": { "$dayOfMonth": "$first_level.second_level.third_level.forth_level.sales_date" }
      }
    }.
    "price": "$first_level.second_level.third_level.forth_level.price"
  }
  ...
}}

Sử dụng $ dateFromParts toán tử tổng hợp ngày khác khác để trích xuất thông tin "ngày" và trình bày ngày trở lại trong biểu mẫu đó để tích lũy.

Bắt đầu chuẩn hóa

Điều cần làm rõ từ "mớ hỗn độn" ở trên là làm việc với các mảng lồng nhau không chính xác là dễ dàng. Các cấu trúc như vậy thường thậm chí không thể cập nhật nguyên tử trong các bản phát hành trước MongoDB 3.6 và ngay cả khi bạn thậm chí chưa bao giờ cập nhật chúng hoặc sống với việc thay thế về cơ bản toàn bộ mảng, chúng vẫn không đơn giản để truy vấn. Đây là những gì bạn đang được hiển thị.

Nơi bạn phải có nội dung mảng trong tài liệu gốc, thông thường nên "làm phẳng" "không chuẩn hóa" cấu trúc như vậy. Điều này có vẻ trái ngược với tư duy quan hệ, nhưng đó thực sự là cách tốt nhất để xử lý dữ liệu đó vì lý do hiệu suất:

{
  "_id": 1,
  "data": [
    {
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },

    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-01"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-02"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "B",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },
    {
     "first_item": "A",
     "second_item": "A",
     "third_item": "B",
     "price": 1,
     "sales_date": new Date("2018-11-03"),
     "quantity": 1
    },
    {
      "first_item": "A",
      "second_item": "B",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
     },
  ]
},
{
  "_id": 2,
  "data": [
    {
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 2,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-10-31"),
      "quantity": 1
    },
    { 
      "first_item": "A",
      "second_item": "A",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
    }
  ]
},
{
  "_id": 3,
  "data": [
    {
      "first_item": "A",
      "second_item": "B",
      "third_item": "A",
      "price": 1,
      "sales_date": new Date("2018-11-03"),
      "quantity": 1
     }
  ]
}

Đó là tất cả dữ liệu giống như được hiển thị ban đầu, nhưng thay vì lồng nhau chúng tôi thực sự chỉ đặt mọi thứ vào một mảng phẳng đơn lẻ trong mỗi tài liệu mẹ. Chắc chắn điều này có nghĩa là trùng lặp của nhiều điểm dữ liệu khác nhau, nhưng sự khác biệt về độ phức tạp và hiệu suất truy vấn phải được thể hiện rõ ràng:

db.collection.aggregate([
  { "$match": {
    "data": {
      "$elemMatch": {
        "first_item": "A",
        "second_item": "A",
        "third_item": "A",
        "sales_date": {
          "$gte": new Date("2018-11-01"),
          "$lt": new Date("2018-12-01")
        }
      }
    }
  }},
  { "$addFields": {
    "data": {
      "$filter": {
        "input": "$data",
         "cond": {
           "$and": [
             { "$eq": [ "$$this.first_item", "A" ] },
             { "$eq": [ "$$this.second_item", "A" ] },
             { "$eq": [ "$$this.third_item", "A" ] },
             { "$gte": [ "$$this.sales_date", new Date("2018-11-01") ] },
             { "$lt": [ "$$this.sales_date", new Date("2018-12-01") ] }
           ]
         }
      }
    }
  }},
  { "$unwind": "$data" },
  { "$group": {
    "_id": {
      "date": "$data.sales_date",
      "price": "$data.price",
    },
    "quantity_sold": { "$avg": "$data.quantity" }
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quantity_sold": "$quantity_sold"
      }
    },
    "quantity_sold": { "$avg": "$quantity_sold" }
  }}
])

Bây giờ, thay vì lồng chúng $ elemMatch và tương tự cho $ filter các biểu thức, mọi thứ rõ ràng và dễ đọc hơn nhiều và thực sự khá đơn giản trong quá trình xử lý. Có một lợi thế khác là bạn thực sự có thể lập chỉ mục các khóa của các phần tử trong mảng như được sử dụng trong truy vấn. Đó là một hạn chế của lồng nhau mô hình trong đó MongoDB đơn giản là sẽ không cho phép "Lập chỉ mục nhiều khóa" trên các khóa của mảng trong mảng . Với một mảng duy nhất, điều này được cho phép và có thể được sử dụng để cải thiện hiệu suất.

Mọi thứ sau "lọc nội dung mảng" sau đó vẫn giống hệt nhau, ngoại trừ tên đường dẫn như "data.sales_date" trái ngược với "first_level.second_level.third_level.forth_level.sales_date" dài dòng từ cấu trúc trước đó.

Khi nào KHÔNG nhúng

Cuối cùng, một quan niệm sai lầm lớn khác là TẤT CẢ các mối quan hệ cần được dịch là nhúng bên trong các mảng. Đây thực sự không bao giờ là mục đích của MongoDB và bạn chỉ có ý định giữ dữ liệu "có liên quan" trong cùng một tài liệu trong một mảng trong trường hợp nó có nghĩa là thực hiện một lần truy xuất dữ liệu thay vì "tham gia".

Mô hình "Đơn đặt hàng / Chi tiết" cổ điển ở đây thường áp dụng khi trong thế giới hiện đại, bạn muốn hiển thị "tiêu đề" cho "Đơn hàng" với các chi tiết như địa chỉ khách hàng, tổng số đơn đặt hàng, v.v. trong cùng một "màn hình" với chi tiết của các chi tiết đơn hàng khác nhau trên "Đơn đặt hàng".

Quay trở lại thời kỳ khởi đầu của RDBMS, màn hình 80 ký tự x 25 dòng điển hình chỉ đơn giản là có thông tin "tiêu đề" như vậy trên một màn hình, sau đó các dòng chi tiết cho mọi thứ đã mua nằm trên một màn hình khác. Vì vậy, tự nhiên có một số mức độ thông thường để lưu trữ chúng trong các bảng riêng biệt. Khi thế giới chuyển sang chi tiết hơn trên những "màn hình" như vậy, bạn thường muốn xem toàn bộ hoặc ít nhất là "tiêu đề" và rất nhiều dòng đầu tiên của một "thứ tự" như vậy.

Do đó, tại sao cách sắp xếp này lại có ý nghĩa khi đưa vào một mảng, vì MongoDB trả về một "tài liệu" chứa tất cả dữ liệu liên quan cùng một lúc. Không cần yêu cầu riêng cho các màn hình được hiển thị riêng biệt và không cần "kết hợp" trên dữ liệu đó vì dữ liệu đã được "tham gia trước" như ban đầu.

Hãy cân nhắc nếu bạn cần nó - AKA "Hoàn toàn" Không chuẩn hóa

Vì vậy, trong trường hợp bạn biết rõ rằng bạn không thực sự quan tâm đến việc xử lý hầu hết dữ liệu trong các mảng như vậy, nói chung sẽ hợp lý hơn nếu chỉ cần đặt tất cả vào một bộ sưu tập của riêng nó với chỉ một thuộc tính khác trong để xác định "cha mẹ" đôi khi cần phải có "tham gia" như vậy:

{
  "_id": 1,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{ 
  "_id": 2,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-01"),
  "quantity": 1
},
{ 
  "_id": 3,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-02"),
  "quantity": 1
},
{ 
  "_id": 4,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "B",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{
  "_id": 5,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "A",
  "third_item": "B",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 6,
  "parent_id": 1,
  "first_item": "A",
  "second_item": "B",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 7,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 2,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{ 
  "_id": 8,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-10-31"),
  "quantity": 1
},
{ 
  "_id": 9,
  "parent_id": 2,
  "first_item": "A",
  "second_item": "A",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
},
{
  "_id": 10,
  "parent_id": 3,
  "first_item": "A",
  "second_item": "B",
  "third_item": "A",
  "price": 1,
  "sales_date": new Date("2018-11-03"),
  "quantity": 1
}

Một lần nữa, đó là cùng một dữ liệu, nhưng chỉ là lần này trong các tài liệu hoàn toàn riêng biệt với tham chiếu đến nguồn gốc tốt nhất trong trường hợp bạn có thể thực sự cần nó cho mục đích khác. Lưu ý rằng tất cả các tổng hợp ở đây hoàn toàn không liên quan đến dữ liệu gốc và cũng rõ ràng là nơi hiệu suất bổ sung và độ phức tạp bị loại bỏ đến bằng cách chỉ cần lưu trữ trong một bộ sưu tập riêng biệt:

db.collection.aggregate([
  { "$match": {
    "first_item": "A",
    "second_item": "A",
    "third_item": "A",
    "sales_date": {
      "$gte": new Date("2018-11-01"),
      "$lt": new Date("2018-12-01")
    }
  }},
  { "$group": {
    "_id": {
      "date": "$sales_date",
      "price": "$price"
    },
    "quantity_sold": { "$avg": "$quantity" }
  }},
  { "$group": {
    "_id": "$_id.date",
    "prices": {
      "$push": {
        "price": "$_id.price",
        "quantity_sold": "$quantity_sold"
      }
    },
    "quantity_sold": { "$avg": "$quantity_sold" }
  }}
])

Vì mọi thứ đã là tài liệu nên không cần phải "lọc bớt mảng" hoặc có bất kỳ phức tạp nào khác. Tất cả những gì bạn đang làm là chọn các tài liệu phù hợp và tổng hợp kết quả, với hai bước cuối cùng giống hệt nhau đã có từ trước đến nay.

Với mục đích chỉ đi đến kết quả cuối cùng, điều này hoạt động tốt hơn nhiều so với phương án thay thế ở trên. Truy vấn được đề cập thực sự chỉ quan tâm đến dữ liệu "chi tiết", do đó, cách hành động tốt nhất là tách hoàn toàn chi tiết khỏi nguồn gốc vì nó luôn mang lại lợi ích hiệu suất tốt nhất.

Và điểm tổng thể ở đây là nơi mô hình truy cập thực tế của phần còn lại của ứng dụng KHÔNG BAO GIỜ cần trả về toàn bộ nội dung mảng, thì có lẽ nó không nên được nhúng. Có vẻ như hầu hết các hoạt động "ghi" tương tự như vậy không bao giờ cần phải chạm vào cha mẹ có liên quan và đó là một yếu tố quyết định khác về việc điều này hoạt động hay không.

Kết luận

Thông báo chung là một lần nữa, theo nguyên tắc chung, bạn không bao giờ nên lồng các mảng. Tối đa bạn nên giữ một mảng "số ít" với dữ liệu không chuẩn hóa một phần trong tài liệu gốc liên quan và nơi các mẫu truy cập còn lại thực sự không sử dụng cha và con song song, thì dữ liệu thực sự nên được tách biệt.

Sự thay đổi "lớn" là tất cả những lý do tại sao bạn nghĩ rằng việc chuẩn hóa dữ liệu thực sự là tốt, hóa ra lại là kẻ thù của các hệ thống tài liệu nhúng như vậy. Việc tránh "kết hợp" luôn tốt, nhưng việc tạo cấu trúc lồng nhau phức tạp để xuất hiện dữ liệu "đã tham gia" cũng không bao giờ thực sự hiệu quả vì lợi ích của bạn.

Chi phí đối phó với những gì bạn "nghĩ" là chuẩn hóa thường kết thúc bằng việc lưu trữ bổ sung và duy trì dữ liệu trùng lặp và không chuẩn hóa trong bộ nhớ cuối cùng của bạn.

Cũng lưu ý rằng tất cả các biểu mẫu ở trên đều trả về cùng một tập kết quả. Nó khá dẫn xuất ở chỗ dữ liệu mẫu để nói ngắn gọn chỉ bao gồm các mặt hàng đơn lẻ hoặc nhiều nhất ở những nơi có nhiều điểm giá thì "trung bình" vẫn là 1 vì đó là những gì tất cả các giá trị. Nhưng nội dung để giải thích điều này đã quá dài nên nó thực sự chỉ là "ví dụ":

{
        "_id" : ISODate("2018-11-01T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}
{
        "_id" : ISODate("2018-11-02T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}
{
        "_id" : ISODate("2018-11-03T00:00:00Z"),
        "prices" : [
                {
                        "price" : 1,
                        "quantity_sold" : 1
                },
                {
                        "price" : 2,
                        "quantity_sold" : 1
                }
        ],
        "quantity_sold" : 1
}



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongorestore mong đợi loại tệp hoặc thư mục nào khi sử dụng cờ -d?

  2. MongoDB được cài đặt qua Homebrew không hoạt động

  3. Toán tử '$ size' không hợp lệ trong tổng hợp

  4. Cập nhật cùng một thuộc tính của mọi tài liệu của bộ sưu tập mongoDb với các giá trị khác nhau

  5. Play-Framework 2.4.x được sử dụng với MongoDB và Java 8