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

Cách tìm tài liệu và tài liệu phụ duy nhất phù hợp với các tiêu chí đã cho trong bộ sưu tập MongoDB

Những gì bạn đang tìm kiếm là vị trí $ toán tử và "phép chiếu". Đối với một trường, bạn cần đối sánh với phần tử mảng bắt buộc bằng cách sử dụng "ký hiệu dấu chấm", đối với nhiều trường, hãy sử dụng $elemMatch :

db.products.find(
    { "items.date": "31.08.2014" },
    { "shop": 1, "name":1, "items.$": 1 }
)

Hoặc $elemMatch cho nhiều trường phù hợp:

db.products.find(
    { "items":  { 
        "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
    }},
    { "shop": 1, "name":1, "items.$": 1 }
)

Tuy nhiên, chúng chỉ hoạt động cho một phần tử mảng duy nhất và chỉ một phần tử sẽ được trả về. Nếu bạn muốn nhiều hơn một phần tử mảng được trả về từ các điều kiện của mình thì bạn cần xử lý nâng cao hơn với khung tổng hợp.

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$unwind": "$items" },
    { "$match": { "items.date": "31.08.2014" } },
    { "$group": {
        "_id": "$_id",
        "shop": { "$first": "$shop" },
        "name": { "$first": "$name" },
        "items": { "$push": "$items" }
    }}
])

Hoặc có thể ở dạng ngắn hơn / nhanh hơn kể từ MongoDB 2.6 trong đó mảng các mục của bạn chứa các mục nhập duy nhất:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$project": {
        "shop": 1,
        "name": 1,
        "items": {
            "$setDifference": [
                { "$map": {
                    "input": "$items",
                    "as": "el",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.date", "31.08.2014" ] },
                            "$$el",
                            false 
                        ]
                    }
                }},
                [false]
            ]
        }
    }}
])

Hoặc có thể với $redact , nhưng có một chút giả thiết:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$redact": {
        "$cond": [
             { "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
             "$$DESCEND",
             "$$PRUNE"
         ]
    }}
])

Hiện đại hơn, bạn sẽ sử dụng $filter :

db.products.aggregate([
  { "$match": { "items.date": "31.08.2014" } },
  { "$addFields": {
    "items": {
      "input": "$items",
      "cond": { "$eq": [ "$$this.date", "31.08.2014" ] }
    }
  }}
])

Và với nhiều điều kiện, $elemMatch$and trong $filter :

db.products.aggregate([
  { "$match": { 
    "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
  }},
  { "$addFields": {
    "items": {
      "input": "$items",
      "cond": { 
        "$and": [
          { "$eq": [ "$$this.date", "31.08.2014" ] },
          { "$eq": [ "$$this.purchasePrice", 1 ] }
        ]
      }
    }
  }}
])

Vì vậy, nó chỉ phụ thuộc vào việc bạn luôn mong đợi một phần tử duy nhất phù hợp hay nhiều phần tử, và sau đó cách tiếp cận nào tốt hơn. Nhưng nếu có thể thì .find() phương pháp nói chung sẽ nhanh hơn vì nó không thiếu chi phí của các hoạt động khác, mà trong những hoạt động cuối cùng với biểu mẫu không bị tụt hậu xa như vậy chút nào.

Lưu ý thêm, "ngày tháng" của bạn được biểu diễn dưới dạng chuỗi, đây không phải là một ý kiến ​​hay về sau. Cân nhắc thay đổi những điều này thành Ngày thích hợp loại đối tượng, điều này sẽ giúp bạn rất nhiều trong tương lai.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Làm cách nào để truy xuất tài liệu bằng _id?

  2. Truy vấn Mongoose về tình trạng ngày không có kết quả, MongoDB Shell hoạt động

  3. Các trường kết quả Mongoose / MongoDB xuất hiện không xác định trong Javascript

  4. Mongoose chọn các trường (lồng nhau)

  5. Cách đăng dữ liệu MongoDB lên mảng lồng nhau bằng cách sử dụng NODE.js và Express