Hãy

Mô tả

Xác định các biến tạm thời có thể được tham chiếu trong các giai đoạn tiếp theo của quy trình.

Các biến được tạo trong giai đoạn let(...) không được đưa vào kết quả cuối cùng, trừ phi chúng được chỉ định rõ ràng cho một trường ở giai đoạn sau (ví dụ: sử dụng add_fields(...) hoặc select(...)). Điều này cho phép bạn đơn giản hoá logic phức tạp bằng cách chia logic đó thành các thành phần nhỏ hơn, có thể dùng lại mà không làm lộn xộn các tài liệu đầu ra. Giai đoạn let(...) đặc biệt hữu ích cho các quy trình con tương quan, trong đó một quy trình con cần tham chiếu đến một giá trị từ phạm vi của tài liệu mẹ.

Ví dụ

Node.js

const results = await db.pipeline()
  .collection("/awards")
  // `let(...)` referred to as `define(...)` in the Web SDK.
  .define(rand().as("r"))
  .addFields(
    switchOn(
      lessThan(variable("r"), 0.05), constant("rare"),
      lessThan(variable("r"), 0.25), constant("uncommon"),
      constant("common")).as("random_score"))
  .execute();

Hành vi

Biến so với Trường

Trong khi các trường biểu thị dữ liệu được lưu trữ trong tài liệu, các biến là các giá trị tạm thời chỉ tồn tại trong quá trình thực thi quy trình.

Trường Biến
Mục đích truy cập hoặc lưu trữ các trường vào tài liệu tạo hoặc truy cập vào các giá trị tạm thời trong quá trình thực thi quy trình
Sử dụng SDK field("name") variable("name")
Phạm vi cục bộ đối với tài liệu hiện tại từ toàn cầu đến đường ống và đường ống phụ
Tham chiếu chưa xác định đánh giá thành absent tạo lỗi thời gian chạy

Phạm vi:

Mặc dù các trường được giới hạn trong tài liệu cục bộ, nhưng các biến được xác định trong một phạm vi riêng biệt và vẫn có thể truy cập được trên các giai đoạn cho đến khi xuất hiện lần đầu tiên một giai đoạn "hợp nhất" nhiều tài liệu với nhau (chẳng hạn như aggregate(...) hoặc distinct(...)). Các giai đoạn "hợp nhất" nhiều tài liệu không cho phép sử dụng các tham chiếu biến sau đó vì bằng cách hợp nhất kết quả của giai đoạn trước với nhau, sẽ không còn một giá trị nào cho biến nữa.

Nên: Tham chiếu một biến sau khi lọc các trường của tài liệu.

Node.js

const results = db.pipeline()
  .collection("/awards")
  .define(min(field("score").abs(), constant(100)).as("normalized_score"))
  .select(field("__name__"), field("owner_id"))
  // Successfully able to use the variable.
  .where(variable("normalized_score").greaterThan(10))
  .execute();

Không: Tham chiếu một biến sau một phép tổng hợp.

Node.js

const results = db.pipeline()
  .collection("/awards")
  .define(min(field("score").abs(), constant(100)).as("normalized_score"))
  .aggregate({
    accumulators: [ field("score").avg().as("avg_score") ],
    groups: [ field("owner_id") ]
  })
  // Attempting to use the variable throws a request validation error.
  .where(variable("normalized_score").greaterThan(10))
  .execute();

Tham chiếu chưa xác định:

Mặc dù việc tham chiếu đến một trường không xác định là không có vấn đề gì (và chỉ đánh giá thành absent), nhưng việc cố gắng tham chiếu đến một biến không xác định sẽ không thành công trong quá trình xác thực yêu cầu. Theo nghĩa này, các tham chiếu trường có thể được xem là thực hiện một thao tác tra cứu trong bản đồ tại thời gian chạy, trong khi các tham chiếu biến giống với các biến trong một ngôn ngữ lập trình được biên dịch tĩnh.

Phạm vi trên toàn cầu và truy vấn phụ

Biến là yếu tố cần thiết khi làm việc với các quy trình lồng nhau. Một quy trình con sẽ thực thi trong phạm vi riêng và chỉ có thể truy cập vào các trường của những tài liệu mà quy trình con đó đang xử lý. Để sử dụng một giá trị từ tài liệu "mẹ" bên trong một truy vấn phụ, trước tiên, bạn phải xác định giá trị đó dưới dạng một biến bằng cách sử dụng giai đoạn let(...).

Node.js

// Fetch reviewers alongside their negative reviews.
const pipeline = db.pipeline()
  .collection("/reviewers")
  // `let(...)` referred to as `define(...)` in the Web SDK.
  .define(field("__name__").as("reviewer_name"))
  .select("__name__", array(db.pipeline().collectionGroup("reviews")
    .where(field("author").equals(variable("reviewer_name")))
    .where(field("rating").lessThan(2))
    .select("review", "rating")).as("negative_reviews"))
  .execute();

Biến trùng lặp

Việc xác định một biến bằng tên đã được xác định ở giai đoạn let(...) trước đó sẽ ghi đè biến trước đó. Bạn có thể dùng trạng thái này để cập nhật trạng thái tạm thời khi quy trình diễn ra.

Các biến được tham chiếu trong quy trình con tuân theo các quy tắc phạm vi từ vựng như trong nhiều ngôn ngữ lập trình và đề cập đến các biến có cùng tên do quy trình gần nhất (quy trình mẹ) xác định.

So sánh với add_fields(...)

Giai đoạn let(...) hoạt động tương tự như giai đoạn add_fields(...), nhưng thay vì thêm các trường vào tài liệu, giai đoạn này sẽ chỉ định giá trị cho các biến.