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

Bao gồm có điều kiện các giai đoạn đường ống tổng hợp

Những gì bạn muốn làm là xây dựng toàn bộ đường ống tùy thuộc vào các tùy chọn được cung cấp. Xét cho cùng thì nó cũng chỉ là một cấu trúc dữ liệu.

Bạn cũng đang kiểm tra không chính xác cho một "mảng" và bạn nên sử dụng instanceof bởi vì typeof thực sự sẽ trả về "object" chứ không phải "array" .

Hơn nữa, bạn thực sự muốn điều kiện đó trong lần đầu tiên giai đoạn chuyển tiếp để chọn tài liệu một cách tối ưu cũng như được thêm vào sau $unwind khi cần thiết:

var pipeline = [
  { $match: 
      Object.assign(
        { 'shop.nameSlug' : req.query.nameSlug },
        (req.query.status) 
          ? { "status.status": (req.query.status instanceof Array)
            ? { "$in": req.query.status } : req.query.status }
          : {}
      )
  },
  { $unwind: "$status" },
  ...(
    (req.query.status)
      ? [{ "$match": { 
          "status.status": (req.query.status instanceof Array)
           ? { "$in": req.query.status } : req.query.status
       }}]
      : []
    ),
    { $group: {
      _id: "$_id",
      status: { $addToSet: "$status" },
      number: { $first: "$number" },
      date: { $first: "$date" },
      comment: { $first: "$comment" }
    }}
];    


Order.aggregate(pipeline).exec(function(err, orders){

})

Đưa ra một req đối tượng với một cái gì đó hiện diện ở trạng thái status bạn nhận được:

// Example stucture
var req = {
  query: { 
   nameSlug: "Bill", 
   status: "A"
  },
};

// Pipeline output as:

[
    {
        "$match" : {
            "shop.nameSlug" : "Bill",
            "status.status" : "A"
        }
    },
    {
        "$unwind" : "$status"
    },
    {
        "$match" : {
            "status.status" : "A"
        }
    },
    {
        "$group" : {
            "_id" : "$_id",
            "status" : {
                "$addToSet" : "$status"
            },
            "number" : {
                "$first" : "$number"
            },
            "date" : {
                "$first" : "$date"
            },
            "comment" : {
                "$first" : "$comment"
            }
        }
    }
]

Với một mảng:

var req = {
  query: { 
   nameSlug: "Bill", 
   status: ["A","B"]
  },
};

// Pipeline output as:
[
    {
        "$match" : {
            "shop.nameSlug" : "Bill",
            "status.status" : {
                "$in" : [ 
                    "A", 
                    "B"
                ]
            }
        }
    },
    {
        "$unwind" : "$status"
    },
    {
        "$match" : {
            "status.status" : {
                "$in" : [ 
                    "A", 
                    "B"
                ]
            }
        }
    },
    {
        "$group" : {
            "_id" : "$_id",
            "status" : {
                "$addToSet" : "$status"
            },
            "number" : {
                "$first" : "$number"
            },
            "date" : {
                "$first" : "$date"
            },
            "comment" : {
                "$first" : "$comment"
            }
        }
    }
]

Và không có gì:

var req = {
  query: { 
   nameSlug: "Bill", 
   //status: ["A","B"]
  },
};

// Pipeline output as:
[
    {
        "$match" : {
            "shop.nameSlug" : "Bill"
        }
    },
    {
        "$unwind" : "$status"
    },
    {
        "$group" : {
            "_id" : "$_id",
            "status" : {
                "$addToSet" : "$status"
            },
            "number" : {
                "$first" : "$number"
            },
            "date" : {
                "$first" : "$date"
            },
            "comment" : {
                "$first" : "$comment"
            }
        }
    }
]

Vì vậy, bạn có thể thấy vị trí các phần được đưa vào có điều kiện tùy thuộc vào các giá trị được cung cấp.

Sử dụng $ filter

Bạn thực sự nên sử dụng $filter ở đây thay vào đó. Nó hiệu quả hơn nhiều so với $unwind và bạn thực sự không nhóm bất cứ thứ gì. Tất cả những gì bạn thực sự muốn là các mảng được lọc. Vì vậy, đó là tất cả những gì bạn thêm có điều kiện:

var pipeline = [
  { $match: 
      Object.assign(
        { 'shop.nameSlug' : req.query.nameSlug },
        (req.query.status) 
          ? { "status.status": (req.query.status instanceof Array)
            ? { "$in": req.query.status } : req.query.status }
          : {}
      )
  },
  ...(
    (req.query.status)
      ? [{ "$addFields": { 
          "status": {
            "$filter": {
              "input": "$status",
              "cond": {
                [(req.query.status instanceof Array) ? "$in" : "$eq"]:
                  [ "$$this.status", req.query.status ]
              }
            }    
          }
       }}]
      : []
    )
];

Có sự lựa chọn giữa $in $eq để kiểm tra so sánh, tùy thuộc vào những gì được cung cấp. Bạn có thể tùy chọn gói toàn bộ trong $setUnion nếu bạn "thực sự có ý" sử dụng một "tập hợp" trong kết quả. Nhưng nhìn chung, có vẻ như bạn chỉ muốn "lọc" các giá trị ra khỏi mảng.

Với cùng kỳ vọng về một giá trị duy nhất:

var req = {
  query: { 
   nameSlug: "Bill", 
   //status: ["A","B"]
   status: "A"
  },
};

/* 1 */
[
    {
        "$match" : {
            "shop.nameSlug" : "Bill",
            "status.status" : "A"
        }
    },
    {
        "$addFields" : {
            "status" : {
                "$filter" : {
                    "input" : "$status",
                    "cond" : {
                        "$eq" : [ 
                            "$$this.status", 
                            "A"
                        ]
                    }
                }
            }
        }
    }
]

Một mảng:

var req = {
  query: { 
   nameSlug: "Bill", 
   status: ["A","B"]
  },
};

/* 1 */
[
    {
        "$match" : {
            "shop.nameSlug" : "Bill",
            "status.status" : {
                "$in" : [ 
                    "A", 
                    "B"
                ]
            }
        }
    },
    {
        "$addFields" : {
            "status" : {
                "$filter" : {
                    "input" : "$status",
                    "cond" : {
                        "$in" : [ 
                            "$$this.status", 
                            [ 
                                "A", 
                                "B"
                            ]
                        ]
                    }
                }
            }
        }
    }
]

Hoặc không có gì:

var req = {
  query: { 
   nameSlug: "Bill", 
   //status: ["A","B"]
  },
};

/* 1 */
[
    {
        "$match" : {
            "shop.nameSlug" : "Bill"
        }
    }
]

Nếu bạn không cần lọc, bạn chỉ cần bỏ giai đoạn đường ống bổ sung.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Biến tổng hợp bao gồm $ cond thành DBObject trong java

  2. Làm cách nào để cho phép trường null khi cập nhật trong Mongoose?

  3. oplog bật trên mongod độc lập không dành cho bản sao

  4. Tùy chọn sử dụngFindAndModify không được hỗ trợ

  5. Di chuyển sang MongoDB:cách truy vấn GROUP BY + WHERE