Tổng hợp nhiều danh sách python

Trong bài đăng này, chúng tôi sẽ giải thích một số phương pháp và kỹ thuật có thể được sử dụng để lấy tổng của hai phần tử danh sách trong danh sách cuối cùng

Danh sách Python là tập hợp các phần tử có thể lặp lại có thể chứa bất kỳ loại mục nào trong đó.  

Ở đây, chúng ta sẽ tính tổng của hai hoặc nhiều phần tử Danh sách theo chỉ mục và tạo một danh sách mới từ tổng. Giả sử chúng ta có hai danh sách chứa nhiều mục kiểu số

Tạo hai danh sách Python

# define two lists
list1 = [10, 9, 13, 19, 25, 81, 51]
list2 = [4, 10, 13, 21, 19, 5, 1]

Sử dụng hai danh sách trên, chúng tôi muốn tạo danh sách đầu ra sẽ giống như bên dưới

[14, 19, 26, 40, 44, 86, 52]

Dưới đây là các phương pháp có thể được sử dụng để lấy danh sách mới sẽ chứa tổng các phần tử với chỉ số tương ứng của chúng

Sử dụng zip [] và Hiểu danh sách để lấy tổng của hai danh sách

Đây là một cách Pythonic để tạo một danh sách mới sẽ chứa tổng các mục. Chúng tôi sẽ sử dụng chức năng zip[] và Danh sách hiểu cho điều đó

Mã ví dụ

# define two lists
list1 = [10, 9, 13, 19, 25, 81, 51]
list2 = [4, 10, 13, 21, 19, 5, 1]

# use zip[] function to calculate the sum of lists
result = [x + y for x, y in zip[list1, list2]]

# print the result
print[result]

đầu ra

[14, 19, 26, 40, 44, 86, 52]

Nếu bạn có một danh sách các danh sách và muốn lấy danh sách chứa tổng của hai danh sách thì bạn có thể sử dụng ví dụ mã bên dưới

my_list = [[10, 20, 30, 40, 10], [30, 10, 40, 20, 5]]

result_list = [sum[x] for x in zip[*my_list]]

print[result_list]

đầu ra

[40, 30, 70, 60, 15]

Phương pháp 2. Sử dụng các hàm map[] và lambda

Chúng ta cũng có thể sử dụng các hàm map[] và lambda để tạo một danh sách chứa tổng của hai danh sách. Chúng tôi đã tạo hai danh sách list1 và list2 tại đây và tạo kết quả danh sách mới bằng cách sử dụng các hàm map và lambda

list[map[lambda a,b: a+b, list1, list2]]

Ví dụ về mã đầy đủ

# define two lists
list1 = [1, 2, 3, 4, 5, 6, 7]
list2 = [10, 20, 30, 40, 50, 60, 70]

# use map[] and lambda function to get the sum
result = list[map[lambda a,b: a+b, list1, list2]]

# print the result
print[result]

đầu ra

[14, 19, 26, 40, 44, 86, 52]

Phương pháp 3. Sử dụng hàm add[] numpy

Nếu bạn đang sử dụng numty trong dự án của mình thì bạn có thể sử dụng hàm add[] của nó để tạo tổng của hai danh sách. Dưới đây là ví dụ mã

Hướng dẫn lập trình Beam dành cho người dùng Beam muốn sử dụng Beam SDK để tạo quy trình xử lý dữ liệu. Nó cung cấp hướng dẫn sử dụng các lớp Beam SDK để xây dựng và kiểm tra quy trình của bạn. Hướng dẫn lập trình không nhằm mục đích tham khảo toàn diện, mà là hướng dẫn cấp cao, không phụ thuộc vào ngôn ngữ để lập trình quy trình Beam của bạn. Khi hướng dẫn lập trình được điền vào, văn bản sẽ bao gồm các mẫu mã bằng nhiều ngôn ngữ để giúp minh họa cách triển khai các khái niệm Beam trong quy trình của bạn

Nếu bạn muốn giới thiệu ngắn gọn về các khái niệm cơ bản của Beam trước khi đọc hướng dẫn lập trình, hãy xem trang Khái niệm cơ bản về mô hình Beam

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

SDK Python hỗ trợ Python 3. 7, 3. 8, 3. 9 và 3. 10

Go SDK hỗ trợ Go v1. 18+. Bản phát hành SDK 2. 32. 0 là phiên bản thử nghiệm cuối cùng

Typescript SDK hỗ trợ Node v16+ và vẫn đang thử nghiệm

1. Tổng quan

Để sử dụng Beam, trước tiên bạn cần tạo một chương trình trình điều khiển bằng cách sử dụng các lớp trong một trong các Beam SDK. Chương trình trình điều khiển của bạn xác định đường dẫn của bạn, bao gồm tất cả đầu vào, biến đổi và đầu ra; . Chúng bao gồm Trình chạy đường ống, đến lượt nó, xác định đường ống của bạn sẽ chạy trên back-end nào

Beam SDK cung cấp một số khái niệm trừu tượng giúp đơn giản hóa cơ chế xử lý dữ liệu phân tán quy mô lớn. Các bản tóm tắt Beam giống nhau hoạt động với cả nguồn dữ liệu hàng loạt và luồng dữ liệu. Khi bạn tạo quy trình Beam, bạn có thể nghĩ về tác vụ xử lý dữ liệu của mình theo các khái niệm trừu tượng này. Chúng bao gồm

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. Một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 gói gọn toàn bộ tác vụ xử lý dữ liệu của bạn, từ đầu đến cuối. Điều này bao gồm đọc dữ liệu đầu vào, chuyển đổi dữ liệu đó và ghi dữ liệu đầu ra. Tất cả các chương trình trình điều khiển Beam phải tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. Khi bạn tạo
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68, bạn cũng phải chỉ định các tùy chọn thực thi để cho
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 biết vị trí và cách thức chạy

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. Một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 đại diện cho một tập dữ liệu phân tán mà đường dẫn Beam của bạn hoạt động trên đó. Tập dữ liệu có thể được giới hạn, nghĩa là nó đến từ một nguồn cố định như tệp hoặc không bị giới hạn, nghĩa là nó đến từ một nguồn cập nhật liên tục thông qua đăng ký hoặc cơ chế khác. Quy trình của bạn thường tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 ban đầu bằng cách đọc dữ liệu từ nguồn dữ liệu bên ngoài, nhưng bạn cũng có thể tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 từ dữ liệu trong bộ nhớ trong chương trình trình điều khiển của mình. Từ đó,
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 là đầu vào và đầu ra cho từng bước trong quy trình của bạn

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78. Một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 đại diện cho một thao tác xử lý dữ liệu hoặc một bước trong quy trình của bạn. Mỗi
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 lấy một hoặc nhiều đối tượng
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 làm đầu vào, thực hiện chức năng xử lý mà bạn cung cấp trên các phần tử của
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 đó và tạo ra không hoặc nhiều đối tượng đầu ra
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    84. SDK Go có một biến phạm vi rõ ràng được sử dụng để xây dựng một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68. Một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 có thể trả về phạm vi gốc của nó bằng phương thức
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    87. Biến phạm vi được truyền cho các hàm
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 để đặt chúng trong
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 sở hữu
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    84
  • biến đổi vào/ra. Beam đi kèm với một số “IO” - thư viện
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 đọc hoặc ghi dữ liệu vào các hệ thống lưu trữ bên ngoài khác nhau

Một chương trình điều khiển Beam điển hình hoạt động như sau

  • Tạo một đối tượng
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    68 và đặt các tùy chọn thực thi đường ống, bao gồm cả Trình chạy đường ống
  • Tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 ban đầu cho dữ liệu đường ống, bằng cách sử dụng IO để đọc dữ liệu từ hệ thống lưu trữ bên ngoài hoặc sử dụng biến đổi
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    94 để tạo một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 từ dữ liệu trong bộ nhớ
  • Áp dụng
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 cho mỗi
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. Biến đổi có thể thay đổi, lọc, nhóm, phân tích hoặc xử lý các phần tử trong một
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73. Một phép biến đổi tạo ra một đầu ra mới
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 mà không sửa đổi bộ sưu tập đầu vào. Một quy trình điển hình lần lượt áp dụng các biến đổi tiếp theo cho từng đầu ra mới
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 cho đến khi quá trình xử lý hoàn tất. Tuy nhiên, lưu ý rằng một đường ống không nhất thiết phải là một đường thẳng duy nhất gồm các phép biến đổi được áp dụng lần lượt. nghĩ về
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 là biến và
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    78 là hàm áp dụng cho các biến này. hình dạng của đường ống có thể là một biểu đồ xử lý phức tạp tùy ý
  • Sử dụng IO để viết
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73[s] cuối cùng, được chuyển đổi thành nguồn bên ngoài
  • Chạy đường ống bằng Trình chạy đường ống được chỉ định

Khi bạn chạy chương trình trình điều khiển Beam, Trình chạy đường ống mà bạn chỉ định sẽ xây dựng biểu đồ quy trình công việc của đường ống của bạn dựa trên

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 đối tượng bạn đã tạo và các biến đổi mà bạn đã áp dụng. Biểu đồ đó sau đó được thực thi bằng cách sử dụng back-end xử lý phân tán thích hợp, trở thành một “công việc” không đồng bộ [hoặc tương đương] trên back-end đó

2. Tạo một đường ống dẫn

Phần trừu tượng

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 gói gọn tất cả dữ liệu và các bước trong tác vụ xử lý dữ liệu của bạn. Chương trình trình điều khiển Beam của bạn thường bắt đầu bằng cách xây dựng một đối tượng Pipeline Pipeline , sau đó sử dụng đối tượng đó làm cơ sở để tạo .

Để sử dụng Beam, trước tiên chương trình trình điều khiển của bạn phải tạo một phiên bản của lớp Beam SDK

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 [thường là trong hàm
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
09]. Khi bạn tạo
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68, bạn cũng sẽ cần đặt một số tùy chọn cấu hình. Bạn có thể đặt các tùy chọn cấu hình cho đường dẫn của mình theo chương trình, nhưng việc đặt các tùy chọn trước [hoặc đọc chúng từ dòng lệnh] và chuyển chúng đến đối tượng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 khi bạn tạo đối tượng thường dễ dàng hơn

Đường ống trong TypeScript API chỉ đơn giản là một chức năng sẽ được gọi với một đối tượng `root` duy nhất và được truyền cho phương thức `run` của Người chạy

// Start by defining the options for the pipeline.
PipelineOptions options = PipelineOptionsFactory.create[];

// Then create the pipeline.
Pipeline p = Pipeline.create[options];

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];

2. 1. Định cấu hình tùy chọn đường ống

Sử dụng các tùy chọn đường ống để định cấu hình các khía cạnh khác nhau của đường ống của bạn, chẳng hạn như trình chạy đường ống sẽ thực thi đường ống của bạn và bất kỳ cấu hình cụ thể nào của trình chạy theo yêu cầu của trình chạy đã chọn. Các tùy chọn quy trình của bạn có khả năng sẽ bao gồm thông tin như ID dự án của bạn hoặc vị trí lưu trữ tệp

Khi bạn chạy quy trình trên một trình chạy mà bạn chọn, một bản sao của PipelineOptions sẽ có sẵn cho mã của bạn. Ví dụ: nếu bạn thêm tham số PipelineOptions vào phương thức

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 của DoFn, tham số đó sẽ được hệ thống điền vào

2. 1. 1. Đặt PipelineOptions từ đối số dòng lệnh

Mặc dù bạn có thể định cấu hình quy trình của mình bằng cách tạo một đối tượng

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 và đặt trường trực tiếp, SDK Beam bao gồm trình phân tích cú pháp dòng lệnh mà bạn có thể sử dụng để đặt trường trong
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 bằng cách sử dụng đối số dòng lệnh

Để đọc các tùy chọn từ dòng lệnh, hãy xây dựng đối tượng

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 của bạn như được minh họa trong mã ví dụ sau

Sử dụng cờ Go để phân tích các đối số dòng lệnh để định cấu hình đường dẫn của bạn. Cờ phải được phân tích cú pháp trước khi

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
16 được gọi

Bất kỳ đối tượng Javascript nào cũng có thể được sử dụng làm tùy chọn đường dẫn. Người ta có thể xây dựng một cách thủ công, nhưng cũng thường truyền một đối tượng được tạo từ các tùy chọn dòng lệnh, chẳng hạn như

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
17

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];

Điều này diễn giải các đối số dòng lệnh tuân theo định dạng

--=

Việc thêm phương thức

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
18 sẽ kiểm tra các đối số dòng lệnh bắt buộc và xác thực các giá trị đối số.

Xây dựng

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 của bạn theo cách này cho phép bạn chỉ định bất kỳ tùy chọn nào làm đối số dòng lệnh

Xác định các biến cờ theo cách này cho phép bạn chỉ định bất kỳ tùy chọn nào làm đối số dòng lệnh

Ghi chú. Đường dẫn ví dụ về WordCount trình bày cách đặt các tùy chọn đường dẫn trong thời gian chạy bằng cách sử dụng các tùy chọn dòng lệnh

2. 1. 2. Tạo tùy chọn tùy chỉnh

Bạn có thể thêm các tùy chọn tùy chỉnh của riêng mình ngoài

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 tiêu chuẩn

Để thêm các tùy chọn của riêng bạn, hãy xác định giao diện với các phương thức getter và setter cho từng tùy chọn

Ví dụ sau đây cho thấy cách thêm tùy chọn tùy chỉnh
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
21 và
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
22

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
0

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
1

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
2

Bạn cũng có thể chỉ định mô tả, mô tả này sẽ xuất hiện khi người dùng chuyển

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23 làm đối số dòng lệnh và giá trị mặc định

Bạn đặt mô tả và giá trị mặc định bằng chú thích, như sau

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
3

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
4

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
5

Đối với Python, bạn cũng có thể chỉ cần phân tích các tùy chọn tùy chỉnh của mình bằng argparse;

Bạn nên đăng ký giao diện của mình với

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24 và sau đó chuyển giao diện khi tạo đối tượng
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13. Khi bạn đăng ký giao diện của mình với
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24, thì
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23 có thể tìm thấy giao diện tùy chọn tùy chỉnh của bạn và thêm nó vào đầu ra của lệnh
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
23.
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24 cũng sẽ xác thực rằng các tùy chọn tùy chỉnh của bạn tương thích với tất cả các tùy chọn đã đăng ký khác

Mã ví dụ sau đây cho biết cách đăng ký giao diện tùy chọn tùy chỉnh của bạn với

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
24

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
6

Bây giờ quy trình của bạn có thể chấp nhận

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
31 và
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
32 làm đối số dòng lệnh

3. bộ sưu tập

Phần trừu tượng PCollection ______9_______73 đại diện cho một tập dữ liệu đa phần tử có khả năng phân phối. Bạn có thể coi

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là dữ liệu “đường ống”; . Như vậy, nếu bạn muốn làm việc với dữ liệu trong quy trình của mình, dữ liệu đó phải ở dạng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73.

Sau khi bạn đã tạo

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 của mình, bạn sẽ cần bắt đầu bằng cách tạo ít nhất một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 ở một dạng nào đó.
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bạn tạo đóng vai trò là đầu vào cho hoạt động đầu tiên trong quy trình của bạn

3. 1. Tạo một PCCollection

Bạn tạo một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách đọc dữ liệu từ một nguồn bên ngoài bằng cách sử dụng Beam, hoặc bạn có thể tạo một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 dữ liệu được lưu trữ trong một lớp bộ sưu tập trong bộ nhớ trong chương trình trình điều khiển của bạn. Cái trước thường là cách một đường ống sản xuất sẽ nhập dữ liệu; . Cái sau chủ yếu hữu ích cho mục đích thử nghiệm và gỡ lỗi

3. 1. 1. Đọc từ một nguồn bên ngoài

Để đọc từ một nguồn bên ngoài, bạn sử dụng một trong các. Các bộ điều hợp khác nhau về cách sử dụng chính xác của chúng, nhưng tất cả chúng đều đọc từ một số nguồn dữ liệu bên ngoài và trả về một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có các thành phần đại diện cho các bản ghi dữ liệu trong nguồn đó

Mỗi bộ điều hợp nguồn dữ liệu có một biến đổi

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
43; . ______48_______45 ______48_______46
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
47
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
48
, . Đây là cách bạn sẽ đăng ký
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
45
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
46
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
47
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
48
to your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 root to create a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73:

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
7

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
8

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
9

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
0

Xem để tìm hiểu thêm về cách đọc từ các nguồn dữ liệu khác nhau được Beam SDK hỗ trợ

3. 1. 2. Tạo PCollection từ dữ liệu trong bộ nhớ

Để tạo một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ một Java
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59 trong bộ nhớ, bạn sử dụng biến đổi
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 do Beam cung cấp. Giống như
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
43 của bộ điều hợp dữ liệu, bạn áp dụng trực tiếp
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 cho chính đối tượng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 của mình

Là tham số,

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 chấp nhận đối tượng Java
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59 và một đối tượng
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66.
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 chỉ định cách các phần tử trong
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59 nên

Để tạo một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ một
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
70 trong bộ nhớ, bạn sử dụng biến đổi
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 do Beam cung cấp. Áp dụng biến đổi này trực tiếp cho chính đối tượng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 của bạn

Để tạo một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ một
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74 trong bộ nhớ, bạn sử dụng biến đổi
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
75 do Beam cung cấp. Chuyển đường dẫn
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
76 và
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74 tới biến đổi này

Để tạo một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ một
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
79 trong bộ nhớ, bạn sử dụng biến đổi
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 do Beam cung cấp. Áp dụng biến đổi này trực tiếp cho đối tượng
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
81 của bạn

Mã ví dụ sau cho biết cách tạo

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 từ bộ nhớ trong
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
70
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
74 .
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
79
:

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
1

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
2

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
3

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
4

3. 2. Đặc tính bộ sưu tập

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 được sở hữu bởi đối tượng cụ thể
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
68 mà nó được tạo ra; . Ở một số khía cạnh, một lớp
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 giống như một lớp
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
59. Tuy nhiên, một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể khác nhau theo một số cách chính.

3. 2. 1. Loại nguyên tố

Các phần tử của một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể thuộc bất kỳ loại nào, nhưng tất cả phải cùng loại. Tuy nhiên, để hỗ trợ xử lý phân tán, Beam cần có khả năng mã hóa từng phần tử riêng lẻ dưới dạng chuỗi byte [để các phần tử có thể được chuyển cho các công nhân phân tán]. Beam SDK cung cấp cơ chế mã hóa dữ liệu bao gồm mã hóa tích hợp cho các loại thường được sử dụng cũng như hỗ trợ chỉ định mã hóa tùy chỉnh khi cần

3. 2. 2. lược đồ phần tử

Trong nhiều trường hợp, loại phần tử trong

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có cấu trúc có thể xem xét nội tâm. Ví dụ là các bản ghi JSON, Bộ đệm giao thức, Avro và cơ sở dữ liệu. Các lược đồ cung cấp một cách để thể hiện các loại dưới dạng một tập hợp các trường được đặt tên, cho phép các tập hợp biểu cảm hơn

3. 2. 3. tính bất biến

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là bất biến. Sau khi tạo, bạn không thể thêm, xóa hoặc thay đổi các thành phần riêng lẻ. Biến đổi Beam có thể xử lý từng phần tử của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 và tạo dữ liệu đường ống mới [dưới dạng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 mới], nhưng nó không sử dụng hoặc sửa đổi bộ sưu tập đầu vào ban đầu

Ghi chú. Beam SDK tránh sao chép các phần tử không cần thiết, vì vậy nội dung

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là bất biến về mặt logic, không phải là bất biến về mặt vật lý. Các thay đổi đối với các thành phần đầu vào có thể hiển thị đối với các DoFns khác đang thực thi trong cùng một gói và có thể gây ra các vấn đề về tính chính xác. Theo quy định, sẽ không an toàn khi sửa đổi các giá trị được cung cấp cho DoFn

3. 2. 4. Truy cập ngẫu nhiên

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không hỗ trợ truy cập ngẫu nhiên vào các phần tử riêng lẻ. Thay vào đó, Beam Transforms xem xét từng phần tử trong một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 riêng lẻ

3. 2. 5. Kích thước và giới hạn

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 là một “túi” phần tử lớn, bất biến. Không có giới hạn trên về số lượng phần tử mà một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể chứa;

Một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có thể có kích thước giới hạn hoặc không giới hạn. Một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn biểu thị một tập dữ liệu có kích thước cố định, đã biết, trong khi một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn biểu thị một tập dữ liệu có kích thước không giới hạn. Việc một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn hay không có giới hạn phụ thuộc vào nguồn của tập dữ liệu mà nó đại diện. Việc đọc từ nguồn dữ liệu lô, chẳng hạn như tệp hoặc cơ sở dữ liệu, sẽ tạo ra một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn. Việc đọc từ nguồn dữ liệu phát trực tuyến hoặc cập nhật liên tục, chẳng hạn như Pub/Sub hoặc Kafka, sẽ tạo ra một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn [trừ khi bạn yêu cầu rõ ràng là không làm như vậy]

Bản chất bị chặn [hoặc không bị chặn] của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn ảnh hưởng đến cách Beam xử lý dữ liệu của bạn. Có thể xử lý một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có giới hạn bằng cách sử dụng một công việc hàng loạt, công việc này có thể đọc toàn bộ tập dữ liệu một lần và thực hiện xử lý trong một công việc có độ dài hữu hạn. Một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn phải được xử lý bằng cách sử dụng công việc phát trực tuyến chạy liên tục, vì toàn bộ bộ sưu tập không bao giờ có sẵn để xử lý cùng một lúc

Beam sử dụng để phân chia một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 cập nhật liên tục thành các cửa sổ logic có kích thước hữu hạn. Các cửa sổ logic này được xác định bởi một số đặc điểm được liên kết với một phần tử dữ liệu, chẳng hạn như dấu thời gian. Các phép biến đổi tổng hợp [chẳng hạn như
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 và
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15] hoạt động trên cơ sở mỗi cửa sổ — khi tập dữ liệu được tạo, chúng xử lý từng
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 dưới dạng chuỗi liên tiếp của các cửa sổ hữu hạn này

3. 2. 6. dấu thời gian phần tử

Each element in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 has an associated intrinsic timestamp. The timestamp for each element is initially assigned by the that creates the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Sources that create an unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 often assign each new element a timestamp that corresponds to when the element was read or added

Note. Sources that create a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 for a fixed data set also automatically assign timestamps, but the most common behavior is to assign every element the same timestamp [
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
21]

Timestamps are useful for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that contains elements with an inherent notion of time. If your pipeline is reading a stream of events, like Tweets or other social media messages, each element might use the time the event was posted as the element timestamp

You can manually assign timestamps to the elements of a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 if the source doesn’t do it for you. You’ll want to do this if the elements have an inherent timestamp, but the timestamp is somewhere in the structure of the element itself [such as a “time” field in a server log entry]. Beam has that take a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as input and output an identical
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with timestamps attached; see for more information about how to do so

4. Transforms

Transforms are the operations in your pipeline, and provide a generic processing framework. You provide processing logic in the form of a function object [colloquially referred to as “user code”], and your user code is applied to each element of an input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [or more than one
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73]. Depending on the pipeline runner and back-end that you choose, many different workers across a cluster may execute instances of your user code in parallel. The user code running on each worker generates the output elements that are ultimately added to the final output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that the transform produces

Aggregation is an important concept to understand when learning about Beam’s transforms. For an introduction to aggregation, see the Basics of the Beam model

The Beam SDKs contain a number of different transforms that you can apply to your pipeline’s

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. These include general-purpose core transforms, such as or . There are also pre-written included in the SDKs, which combine one or more of the core transforms in a useful processing pattern, such as counting or combining elements in a collection. You can also define your own more complex composite transforms to fit your pipeline’s exact use case

4. 1. Applying transforms

To invoke a transform, you must apply it to the input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Each transform in the Beam SDKs has a generic
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method [or pipe operator
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
32]
. Invoking multiple Beam transforms is similar to method chaining, but with one slight difference. You apply the transform to the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, passing the transform itself as an argument, and the operation returns the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. This takes the general form.

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
5

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
6

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
7

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
8

Bởi vì Beam sử dụng một phương pháp chung

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, nên bạn có thể thực hiện cả hai phép biến đổi chuỗi một cách tuần tự và cũng có thể áp dụng các phép biến đổi có chứa các biến đổi khác được lồng vào bên trong [được gọi trong Beam SDK]

It’s recommended to create a new variable for each new

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to sequentially transform input data.
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84s can be used to create functions that contain other transforms [called in the Beam SDKs]

How you apply your pipeline’s transforms determines the structure of your pipeline. The best way to think of your pipeline is as a directed acyclic graph, where

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 nodes are subroutines that accept
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nodes as inputs and emit
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nodes as outputs. For example, you can chain together transforms to create a pipeline that successively modifies input data. For example, you can successively call transforms on PCollections to modify the input data.

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
9

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
0

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
1

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
2

The graph of this pipeline looks like the following

Figure 1. A linear pipeline with three sequential transforms

However, note that a transform does not consume or otherwise alter the input collection — remember that a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is immutable by definition. This means that you can apply multiple transforms to the same input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to create a branching pipeline, like so

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
3

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
4

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
5

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
6

The graph of this branching pipeline looks like the following

Figure 2. A branching pipeline. Two transforms are applied to a single PCollection of database table rows

You can also build your own that nest multiple transforms inside a single, larger transform. Composite transforms are particularly useful for building a reusable sequence of simple steps that get used in a lot of different places

The pipe syntax allows one to apply PTransforms to

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
44s and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
45s of PCollections as well for those transforms accepting multiple inputs [such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47]

PTransforms can also be applied to any

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48, which include the Root object, PCollections, arrays of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48s, and objects with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48 values. One can apply transforms to these composite types by wrapping them with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
51, e. g.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
52

PTransforms come in two flavors, synchronous and asynchronous, depending on whether their application* involves asynchronous invocations. An

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
53 must be applied with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
54 and returns a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
55 which must be awaited before further pipeline construction

4. 2. Core Beam transforms

Beam provides the following core transforms, each of which represents a different processing paradigm

  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    14
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    47
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    15
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    46
  • from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    61

The Typescript SDK provides some of the most basic of these transforms as methods on

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 itself

4. 2. 1. ParDo

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is a Beam transform for generic parallel processing. The
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 processing paradigm is similar to the “Map” phase of a Map/Shuffle/Reduce-style algorithm. a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform considers each element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, performs some processing function [your user code] on that element, and emits zero, one, or multiple elements to an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is useful for a variety of common data processing operations, including

  • Filtering a data set. You can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to consider each element in a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 and either output that element to a new collection or discard it
  • Formatting or type-converting each element in a data set. If your input
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 contains elements that are of a different type or format than you want, you can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to perform a conversion on each element and output the result to a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73
  • Extracting parts of each element in a data set. If you have a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of records with multiple fields, for example, you can use a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to parse out just the fields you want to consider into a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73
  • Performing computations on each element in a data set. You can use
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 to perform simple or complex computations on every element, or certain elements, of a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 and output the results as a new
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73

In such roles,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 is a common intermediate step in a pipeline. You might use it to extract certain fields from a set of raw input records, or convert raw input into a different format; you might also use
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to convert processed data into a format suitable for output, like database table rows or printable strings

When you apply a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform, you’ll need to provide user code in the form of a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 object.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 is a Beam SDK class that defines a distributed processing function

When you create a subclass of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, note that your subclass should adhere to the

All DoFns should be registered using a generic

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
86 function. This allows the Go SDK to infer an encoding from any inputs/outputs, registers the DoFn for execution on remote runners, and optimizes the runtime execution of the DoFns via reflection

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
7

4. 2. 1. 1. Applying ParDo

Like all Beam transforms, you apply

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 by calling the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method on the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 and passing
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 as an argument, as shown in the following example code

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
91 applies the passed in
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 argument to the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, as shown in the following example code

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
8

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
9

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
0

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
1

In the example, our input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 contains
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96
values. We apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform that specifies a function [
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98] to compute the length of each string, and outputs the result to a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01
values that stores the length of each word.

4. 2. 1. 2. Creating a DoFn

Đối tượng

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 mà bạn chuyển đến
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 chứa logic xử lý được áp dụng cho các phần tử trong bộ sưu tập đầu vào. When you use Beam, often the most important pieces of code you’ll write are these
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s - they’re what define your pipeline’s exact data processing tasks

Note. When you create your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, be mindful of the and ensure that your code follows them

A

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes one element at a time from the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Khi bạn tạo một lớp con của
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, bạn sẽ cần cung cấp các tham số loại phù hợp với loại của các phần tử đầu vào và đầu ra. If your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes incoming
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50 elements and produces
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00 elements for the output collection [like our previous example,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98], your class declaration would look like this

A

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 processes one element at a time from the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. When you create a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 struct, you’ll need to provide type parameters that match the types of the input and output elements in a ProcessElement method. Nếu
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 của bạn xử lý các phần tử
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 đến và tạo ra các phần tử
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01 cho tập hợp đầu ra [như ví dụ trước của chúng tôi,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
98], dofn của bạn có thể trông như thế này

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
2

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
3

Inside your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 subclass, you’ll write a method annotated with
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 where you provide the actual processing logic. You don’t need to manually extract the elements from the input collection; the Beam SDKs handle that for you. Your
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method should accept a parameter tagged with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23, which will be populated with the input element. In order to output elements, the method can also take a parameter of type
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24 which provides a method for emitting elements. The parameter types must match the input and output types of your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 or the framework will raise an error. Ghi chú.
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 và
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24 đã được giới thiệu trong Beam 2. 5. 0;

Inside your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 subclass, you’ll write a method
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 where you provide the actual processing logic. You don’t need to manually extract the elements from the input collection; the Beam SDKs handle that for you. Your
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method should accept an argument
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
32, which is the input element, and return an iterable with its output values. You can accomplish this by emitting individual elements with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
33 statements. You can also use a
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
34 statement with an iterable, like a list or a generator

For your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 type, you’ll write a method
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
36 where you provide the actual processing logic. You don’t need to manually extract the elements from the input collection; the Beam SDKs handle that for you. Your
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
36 method should accept a parameter
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
32, which is the input element. In order to output elements, the method can also take a function parameter, which can be called to emit elements. The parameter types must match the input and output types of your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 or the framework will raise an error

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
4

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
5

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
6

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
7

Simple DoFns can also be written as functions

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
8

Note. Whether using a structural

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 type or a functional
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83, they should be registered with beam in an
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
42 block. Otherwise they may not execute on distributed runners.

Note. If the elements in your input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 are key/value pairs, you can access the key or value by using
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
44 or
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
45, respectively.

Note. If the elements in your input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 are key/value pairs, your process element method must have two parameters, for each of the key and value, respectively. Similarly, key/value pairs are also output as separate parameters to a single
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
47.

A given

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 instance generally gets invoked one or more times to process some arbitrary bundle of elements. However, Beam doesn’t guarantee an exact number of invocations; it may be invoked multiple times on a given worker node to account for failures and retries. As such, you can cache information across multiple calls to your processing method, but if you do so, make sure the implementation does not depend on the number of invocations

In your processing method, you’ll also need to meet some immutability requirements to ensure that Beam and the processing back-end can safely serialize and cache the values in your pipeline. Your method should meet the following requirements

  • You should not in any way modify an element returned by the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    23 annotation or
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    50 [the incoming elements from the input collection].
  • Once you output a value using
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    51 you should not modify that value in any way
  • You should not in any way modify the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    32 argument provided to the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    30 method, or any side inputs.
  • Once you output a value using
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    33 or
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    34, you should not modify that value in any way
  • You should not in any way modify the parameters provided to the
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    36 method, or any side inputs.
  • Once you output a value using an
    // If beamx or Go flags are used, flags must be parsed first,
    // before beam.Init[] is called.
    flag.Parse[]
    47, you should not modify that value in any way
4. 2. 1. 3. Lightweight DoFns and other abstractions

If your function is relatively straightforward, you can simplify your use of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 by providing a lightweight
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 in-line, as an anonymous inner class instance a lambda function an anonymous function a function passed to
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
60 or
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
61
.

Here’s the previous example,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
63, with the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 specified as an anonymous inner class instance a lambda function an anonymous function a function .

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
9

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
0

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
1

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
2

If your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 performs a one-to-one mapping of input elements to output elements–that is, for each input element, it applies a function that produces exactly one output element, you can return that element directly. you can use the higher-level
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
66
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
67
transform.
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
66 can accept an anonymous Java 8 lambda function for additional brevity.

Here’s the previous example using

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
66
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
67
a direct return .

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
3

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
4

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
5

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
6

Note. You can use Java 8 lambda functions with several other Beam transforms, including

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
71,
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
72, and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61.

Note. Anonymous function DoFns may not work on distributed runners. It’s recommended to use named functions and register them with

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
74 in an
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
75 block.

4. 2. 1. 4. DoFn lifecycle

Here is a sequence diagram that shows the lifecycle of the DoFn during the execution of the ParDo transform. The comments give useful information to pipeline developers such as the constraints that apply to the objects or particular cases such as failover or instance reuse. They also give instantiation use cases

4. 2. 2. GroupByKey

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is a Beam transform for processing collections of key/value pairs. It’s a parallel reduction operation, analogous to the Shuffle phase of a Map/Shuffle/Reduce-style algorithm. The input to
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is a collection of key/value pairs that represents a multimap, where the collection contains multiple pairs that have the same key, but different values. Given such a collection, you use
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 to collect all of the values associated with each unique key

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is a good way to aggregate data that has something in common. For example, if you have a collection that stores records of customer orders, you might want to group together all the orders from the same postal code [wherein the “key” of the key/value pair is the postal code field, and the “value” is the remainder of the record]

Let’s examine the mechanics of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 with a simple example case, where our data set consists of words from a text file and the line number on which they appear. We want to group together all the line numbers [values] that share the same word [key], letting us see all the places in the text where a particular word appears

Our input is a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of key/value pairs where each word is a key, and the value is a line number in the file where the word appears. Here’s a list of the key/value pairs in the input collection

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
7

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 gathers up all the values with the same key and outputs a new pair consisting of the unique key and a collection of all of the values that were associated with that key in the input collection. If we apply
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 to our input collection above, the output collection would look like this

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
8

Thus,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 represents a transform from a multimap [multiple keys to individual values] to a uni-map [unique keys to collections of values]

Using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 is straightforward

While all SDKs have a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform, using
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 is generally more natural. The
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 transform can be parameterized by the name[s] of properties on which to group the elements of the PCollection, or a function taking the each element as input that maps to a key on which to do grouping

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
9

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
0

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
1

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
2

4. 2. 2. 1 GroupByKey and unbounded PCollections

If you are using unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, you must use either or an in order to perform a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or . This is because a bounded
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 must wait for all the data with a certain key to be collected, but with unbounded collections, the data is unlimited. Windowing and/or triggers allow grouping to operate on logical, finite bundles of data within the unbounded data streams

If you do apply

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to a group of unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s without setting either a non-global windowing strategy, a trigger strategy, or both for each collection, Beam generates an IllegalStateException error at pipeline construction time

When using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to group
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s that have a applied, all of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s you want to group must use the same windowing strategy and window sizing. For example, all of the collections you are merging must use [hypothetically] identical 5-minute fixed windows, or 4-minute sliding windows starting every 30 seconds

If your pipeline attempts to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s with incompatible windows, Beam generates an IllegalStateException error at pipeline construction time

4. 2. 3. CoGroupByKey

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 performs a relational join of two or more key/value
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s that have the same key type. shows an example pipeline that uses a join

Consider using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 if you have multiple data sets that provide information about related things. For example, let’s say you have two different files with user data. one file has names and email addresses; the other file has names and phone numbers. You can join those two data sets, using the user name as a common key and the other data as the associated values. After the join, you have one data set that contains all of the information [email addresses and phone numbers] associated with each name

If you are using unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, you must use either or an in order to perform a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47. See for more details

In the Beam SDK for Java,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts a tuple of keyed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s [
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
10] as input. For type safety, the SDK requires you to pass each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as part of a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
12. You must declare a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
13 for each input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
12 that you want to pass to
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 returns a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
18, which groups values from all the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s by their common keys. Each key [all of type
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
20] will have a different
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
21, which is a map from
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
22 to
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
23. You can access a specific collection in an
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
21 object by using the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
13 that you supplied with the initial collection

In the Beam SDK for Python,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts a dictionary of keyed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 creates a single output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that contains one key/value tuple for each key in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. Each key’s value is a dictionary that maps each tag to an iterable of the values under they key in the corresponding
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

In the Beam Go SDK,

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 accepts an arbitrary number of
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input. As output,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 creates a single output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that groups each key with value iterator functions for each input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The iterator functions map to input
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
37 in the same order they were provided to the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47

The following conceptual examples use two input collections to show the mechanics of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47

The first set of data has a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40 called
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
41 and contains names and email addresses. The second set of data has a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
40 called
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
43 and contains names and phone numbers

The first set of data contains names and email addresses. The second set of data contains names and phone numbers

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
3

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
4

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
5

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
6

After

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, the resulting data contains all data associated with each unique key from any of the input collections

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
7

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
8

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
9

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
0

The following code example joins the two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s with
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, followed by a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to consume the result. Then, the code uses tags to look up and format data from each collection

Ví dụ mã sau nối hai

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 với
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47, theo sau là một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 để sử dụng kết quả. The ordering of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 iterator parameters maps to the ordering of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
47 inputs

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
1

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
2

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
3

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
4

The formatted data looks like this

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
5

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
6

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
7

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
8

4. 2. 4. Combine

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15
is a Beam transform for combining collections of elements or values in your data.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 has variants that work on entire
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, and some that combine the values for each key in
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of key/value pairs.

Khi bạn áp dụng biến đổi

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, bạn phải cung cấp hàm chứa logic để kết hợp các phần tử hoặc giá trị. The combining function should be commutative and associative, as the function is not necessarily invoked exactly once on all values with a given key. Because the input data [including the value collection] may be distributed across multiple workers, the combining function might be called multiple times to perform partial combining on subsets of the value collection. The Beam SDK also provides some pre-built combine functions for common numeric combination operations such as sum, min, and max

Simple combine operations, such as sums, can usually be implemented as a simple function. More complex combination operations might require you to create a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61 that has an accumulation type distinct from the input/output type.

The associativity and commutativity of a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61 allows runners to automatically apply some optimizations

  • Combiner lifting. This is the most significant optimization. Input elements are combined per key and window before they are shuffled, so the volume of data shuffled might be reduced by many orders of magnitude. Another term for this optimization is “mapper-side combine. ”
  • Incremental combining. When you have a
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    61 that reduces the data size by a lot, it is useful to combine elements as they emerge from a streaming shuffle. This spreads out the cost of doing combines over the time that your streaming computation might be idle. Incremental combining also reduces the storage of intermediate accumulators
4. 2. 4. 1. Simple combinations using simple functions

The following example code shows a simple combine function. Combining is done by modifying a grouping transform with the

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
64 method. Phương thức này nhận ba tham số. the value to combine [either as a named property of the input elements, or a function of the entire input], the combining operation [either a binary function or a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61], and finally a name for the combined value in the output object.

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
9

--=
0

--=
1

--=
2

All Combiners should be registered using a generic

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
66 function. This allows the Go SDK to infer an encoding from any inputs/outputs, registers the Combiner for execution on remote runners, and optimizes the runtime execution of the Combiner via reflection

Combiner1 should be used when your accumulator, input, and output are all of the same type. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
67 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
68 is the type of the input/accumulator/output

Combiner2 should be used when your accumulator, input, and output are 2 distinct types. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
69 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
70 is the type of the accumulator and
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
71 is the other type

Combiner3 should be used when your accumulator, input, and output are 3 distinct types. It can be called with

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
72 where
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
70 is the type of the accumulator,
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
71 is the type of the input, and
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
75 is the type of the output

4. 2. 4. 2. Advanced combinations using CombineFn

For more complex combine functions, you can define a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61. You should use a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61 if the combine function requires a more sophisticated accumulator, must perform additional pre- or post-processing, might change the output type, or takes the key into account.

A general combining operation consists of four operations. When you create a subclass of

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61, you must provide four operations by overriding the corresponding methods.

  1. Create Accumulator creates a new “local” accumulator. In the example case, taking a mean average, a local accumulator tracks the running sum of values [the numerator value for our final average division] and the number of values summed so far [the denominator value]. It may be called any number of times in a distributed fashion

  2. Add Input adds an input element to an accumulator, returning the accumulator value. In our example, it would update the sum and increment the count. It may also be invoked in parallel

  3. Merge Accumulators merges several accumulators into a single accumulator; this is how data in multiple accumulators is combined before the final calculation. In the case of the mean average computation, the accumulators representing each portion of the division are merged together. It may be called again on its outputs any number of times

  4. Trích xuất đầu ra thực hiện tính toán cuối cùng. In the case of computing a mean average, this means dividing the combined sum of all the values by the number of values summed. It is called once on the final, merged accumulator

The following example code shows how to define a

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61 that computes a mean average

--=
3

--=
4

--=
5

--=
6

Note. Only

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
80 is a required method. The others will have a default interpretation based on the accumulator type

4. 2. 4. 3. Combining a PCollection into a single value

Use the global combine to transform all of the elements in a given

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into a single value, represented in your pipeline as a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 containing one element. The following example code shows how to apply the Beam provided sum combine function to produce a single sum value for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of integers

--=
7

--=
8

--=
9

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
0

4. 2. 4. 4. Combine and global windowing

If your input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses the default global windowing, the default behavior is to return a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 containing one item. That item’s value comes from the accumulator in the combine function that you specified when applying
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15. For example, the Beam provided sum combine function returns a zero value [the sum of an empty input], while the min combine function returns a maximal or infinite value

To have

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 instead return an empty
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 if the input is empty, specify
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
89 when you apply your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 transform, as in the following code example

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
1

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
2

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
3

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
4

4. 2. 4. 5. Combine and non-global windowing

If your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses any non-global windowing function, Beam does not provide the default behavior. You must specify one of the following options when applying
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15

  • Specify
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    89, where windows that are empty in the input
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 will likewise be empty in the output collection
  • Specify
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    95, in which the output is immediately converted to a
    const pipeline_options = {
      runner: "default",
      project: "my_project",
    };
    
    const runner = beam.createRunner[pipeline_options];
    
    const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
    
    96, which will provide a default value for each empty window when used as a side input. You’ll generally only need to use this option if the result of your pipeline’s
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    15 is to be used as a side input later in the pipeline

If your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 uses any non-global windowing function, the Beam Go SDK behaves the same way as with global windowing. Windows that are empty in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 will likewise be empty in the output collection

4. 2. 4. 6. Combining values in a keyed PCollection

After creating a keyed PCollection [for example, by using a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform], a common pattern is to combine the collection of values associated with each key into a single, merged value. Drawing on the previous example from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, a key-grouped
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 called
--=
03 looks like this

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
5

In the above

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, each element has a string key [for example, “cat”] and an iterable of integers for its value [in the first element, containing [1, 5, 9]]. If our pipeline’s next processing step combines the values [rather than considering them individually], you can combine the iterable of integers to create a single, merged value to be paired with each key. This pattern of a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 followed by merging the collection of values is equivalent to Beam’s Combine PerKey transform. The combine function you supply to Combine PerKey must be an associative reduction function or a subclass of
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61.

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
6

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
7

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
8

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
9

4. 2. 5. Flatten

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46
is a Beam transform for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that store the same data type.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 merges multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects into a single logical
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73.

The following example shows how to apply a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 transform to merge multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
00

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
01

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
02

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
03

4. 2. 5. 1. Data encoding in merged collections

By default, the coder for the output

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is the same as the coder for the first
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in the input
--=
19. However, the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects can each use different coders, as long as they all contain the same data type in your chosen language

4. 2. 5. 2. Merging windowed collections

When using

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that have a windowing strategy applied, all of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects you want to merge must use a compatible windowing strategy and window sizing. For example, all the collections you’re merging must all use [hypothetically] identical 5-minute fixed windows or 4-minute sliding windows starting every 30 seconds

If your pipeline attempts to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
46 to merge
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects with incompatible windows, Beam generates an
--=
26 error when your pipeline is constructed

4. 2. 6. Partition

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61
is a Beam transform for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 objects that store the same data type.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61 splits a single
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into a fixed number of smaller collections.

Often in the Typescript SDK the

--=
34 transform is more natural to use

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
61 divides the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 according to a partitioning function that you provide. The partitioning function contains the logic that determines how to split up the elements of the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into each resulting partition
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The number of partitions must be determined at graph construction time. You can, for example, pass the number of partitions as a command-line option at runtime [which will then be used to build your pipeline graph], but you cannot determine the number of partitions in mid-pipeline [based on data calculated after your pipeline graph is constructed, for instance]

The following example divides a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into percentile groups

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
04

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
05

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
06

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
07

4. 3. Requirements for writing user code for Beam transforms

When you build user code for a Beam transform, you should keep in mind the distributed nature of execution. For example, there might be many copies of your function running on a lot of different machines in parallel, and those copies function independently, without communicating or sharing state with any of the other copies. Depending on the Pipeline Runner and processing back-end you choose for your pipeline, each copy of your user code function may be retried or run multiple times. As such, you should be cautious about including things like state dependency in your user code

In general, your user code must fulfill at least these requirements

  • Your function object must be serializable
  • Your function object must be thread-compatible, and be aware that the Beam SDKs are not thread-safe

In addition, it’s recommended that you make your function object idempotent. Non-idempotent functions are supported by Beam, but require additional thought to ensure correctness when there are external side effects

Note. These requirements apply to subclasses of

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83[a function object used with the transform],
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61 [a function object used with the transform], and
--=
42 [a function object used with the transform].

Note. These requirements apply to

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s [a function object used with the transform],
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61s [a function object used with the transform], and
--=
42s [a function object used with the transform].

4. 3. 1. Serializability

Any function object you provide to a transform must be fully serializable. This is because a copy of the function needs to be serialized and transmitted to a remote worker in your processing cluster. The base classes for user code, such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83,
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
61, and
--=
42, already implement
--=
49; however, your subclass must not add any non-serializable members. Funcs are serializable as long as they are registered with
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
74 [for simple functions] or
--=
51 [for structural DoFns], and are not closures. Structural
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83s will have all exported fields serialized. Unexported fields are unable to be serialized, and will be silently ignored.
The Typescript SDK use ts-serialize-closures to serialize functions [and other objects]. This works out of the box for functions that are not closures, and also works for closures as long as the function in question [and any closures it references] are compiled with the
--=
53 hooks [e. g. by using
--=
54 in place of
--=
55]. Ngoài ra, người ta có thể gọi
--=
56 để đăng ký một chức năng trực tiếp theo tên có thể ít bị lỗi hơn. Note that if, as is often the case in Javascript,
--=
57 returns objects that contain closures, it is not sufficient to register
--=
57 alone–its return value must be registered if used.

Some other serializability factors you should keep in mind are

  • TransientUnexported fields in your function object are not transmitted to worker instances, because they are not automatically serialized.
  • Avoid loading a field with a large amount of data before serialization
  • Individual instances of your function object cannot share data
  • Mutating a function object after it gets applied will have no effect

Note. Take care when declaring your function object inline by using an anonymous inner class instance. In a non-static context, your inner class instance will implicitly contain a pointer to the enclosing class and that class’ state. That enclosing class will also be serialized, and thus the same considerations that apply to the function object itself also apply to this outer class.

Note. There’s no way to detect if a function is a closure. Closures will cause runtime errors and pipeline failures. Avoid using anonymous functions when possible.

4. 3. 2. Thread-compatibility

Your function object should be thread-compatible. Each instance of your function object is accessed by a single thread at a time on a worker instance, unless you explicitly create your own threads. Note, however, that the Beam SDKs are not thread-safe. If you create your own threads in your user code, you must provide your own synchronization. Note that static members in your function object are not passed to worker instances and that multiple instances of your function may be accessed from different threads.

4. 3. 3. Idempotence

It’s recommended that you make your function object idempotent–that is, that it can be repeated or retried as often as necessary without causing unintended side effects. Non-idempotent functions are supported, however the Beam model provides no guarantees as to the number of times your user code might be invoked or retried; as such, keeping your function object idempotent keeps your pipeline’s output deterministic, and your transforms’ behavior more predictable and easier to debug

4. 4. Side inputs

In addition to the main input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, you can provide additional inputs to a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform in the form of side inputs. A side input is an additional input that your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 can access each time it processes an element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. When you specify a side input, you create a view of some other data that can be read from within the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform’s
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 while processing each element

Side inputs are useful if your

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 needs to inject additional data when processing each element in the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, but the additional data needs to be determined at runtime [and not hard-coded]. Such values might be determined by the input data, or depend on a different branch of your pipeline

All side input iterables should be registered using a generic

--=
67 function. This optimizes runtime execution of the iterable

4. 4. 1. Passing side inputs to ParDo

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
08

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
09

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
10

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
11

4. 4. 2. Side inputs and windowing

A windowed

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 may be infinite and thus cannot be compressed into a single value [or single collection class]. When you create a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
96 of a windowed
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, the
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
96 represents a single entity per window [one singleton per window, one list per window, etc. ]

Beam uses the window[s] for the main input element to look up the appropriate window for the side input element. Beam projects the main input element’s window into the side input’s window set, and then uses the side input from the resulting window. If the main input and side inputs have identical windows, the projection provides the exact corresponding window. Tuy nhiên, nếu đầu vào có các cửa sổ khác nhau, Beam sẽ sử dụng phép chiếu để chọn cửa sổ đầu vào bên thích hợp nhất

For example, if the main input is windowed using fixed-time windows of one minute, and the side input is windowed using fixed-time windows of one hour, Beam projects the main input window against the side input window set and selects the side input value from the appropriate hour-long side input window

If the main input element exists in more than one window, then

--=
72 gets called multiple times, once for each window. Each call to
--=
72 projects the “current” window for the main input element, and thus might provide a different view of the side input each time

If the side input has multiple trigger firings, Beam uses the value from the latest trigger firing. This is particularly useful if you use a side input with a single global window and specify a trigger

4. 5. Additional outputs

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 always produces a main output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [as the return value from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31], you can also have your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 produce any number of additional output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. If you choose to have multiple outputs, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 returns all of the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s [including the main output] bundled together

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
91 always produces an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 can produce any number of additional output
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
37s, or even none at all. If you choose to have multiple outputs, your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 needs to be called with the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 function that matches the number of outputs.
--=
87 for two output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s,
--=
89 for three and so on until
--=
90. If you need more, you can use
--=
91 which will return a
--=
92

While

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 always produces a main output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [as the return value from
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31]. If you want to have multiple outputs, emit an object with distinct properties in your
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 operation and follow this operation with a
--=
34 to break it into multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

4. 5. 1. Tags for multiple outputs

The

--=
34 PTransform will take a PCollection of elements of the form
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
00 and return a object
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
01. The set of expected tags is passed to the operation; how multiple or unknown tags are handled can be specified by passing a non-default
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
02 instance

The Go SDK doesn’t use output tags, and instead uses positional ordering for multiple output PCollections

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
12

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
13

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
14

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
15

4. 5. 2. Emitting to multiple outputs in your DoFn

Call emitter functions as needed to produce 0 or more elements for its matching

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The same value can be emitted with multiple emitters. As normal, do not mutate values after emitting them from any emitter

All emitters should be registered using a generic

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
04 function. This optimizes runtime execution of the emitter

DoFns can also return a single element via the standard return. The standard return is always the first PCollection returned from beam. ParDo. Other emitters output to their own PCollections in their defined parameter order

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
16

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
17

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
18

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
19

4. 5. 3. Accessing additional parameters in your DoFn

In addition to the element and the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24, Beam will populate other parameters to your DoFn’s
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method. Any combination of these parameters can be added to your process method in any order

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method. Any combination of these parameters can be added to your process method in any order

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method. These are available by placing accessors in the context argument, just as for side inputs

In addition to the element, Beam will populate other parameters to your DoFn’s

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
36 method. Any combination of these parameters can be added to your process method in a standard order

context. Context. To support consolidated logging and user defined metrics, a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
10 parameter can be requested. Per Go conventions, if present it’s required to be the first parameter of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
20

Timestamp. To access the timestamp of an input element, add a parameter annotated with

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
12 of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
13. For example

Timestamp. To access the timestamp of an input element, add a keyword parameter default to

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
14. For example

Timestamp. To access the timestamp of an input element, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
15 parameter before the element. For example

Timestamp. To access the window an input element falls into, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
16 to the context argument

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
21

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
22

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
23

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
24

Window. To access the window an input element falls into, add a parameter of the type of the window used for the input

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. If the parameter is a window type [a subclass of
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
18] that does not match the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, then an error will be raised. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
20], then the
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 method will be invoked multiple time for the element, once for each window. For example, when fixed windows are being used, the window is of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
22

Window. To access the window an input element falls into, add a keyword parameter default to

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
23. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
20], then the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 method will be invoked multiple time for the element, once for each window

Window. Để truy cập cửa sổ có phần tử đầu vào, hãy thêm tham số

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
26 trước phần tử. If an element falls in multiple windows [for example, this will happen when using SlidingWindows], then the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
36 method will be invoked multiple time for the element, once for each window. Since
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
26 is an interface it’s possible to type assert to the concrete implementation of the window. For example, when fixed windows are being used, the window is of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
29

Window. To access the window an input element falls into, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
16 to the context argument. If an element falls in multiple windows [for example, this will happen when using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
20], then the function will be invoked multiple time for the element, once for each window

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
25

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
26

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
27

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
28

PaneInfo. When triggers are used, Beam provides a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
32 object that contains information about the current firing. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
32 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key

PaneInfo. When triggers are used, Beam provides a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
34 object that contains information about the current firing. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
34 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key. This feature implementation in Python SDK is not fully completed; see more at Issue 17821

PaneInfo. When triggers are used, Beam provides

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
36 object that contains information about the current firing. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
36 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key

Window. To access the window an input element falls into, add a

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
38 to the context argument. Using
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
36 you can determine whether this is an early or a late firing, and how many times this window has already fired for this key

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
29

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
30

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
31

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
32

Tùy chọn đường ống. The

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13 for the current pipeline can always be accessed in a process method by adding it as a parameter

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
33

Các phương thức

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
41 cũng có thể truy cập nhiều tham số này. Timestamp, Window, key,
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
13,
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
24, and
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
44 parameters can all be accessed in an
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
41 method. In addition, an
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
41 method can take a parameter of type
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
47 which tells whether the timer is based on event time or processing time. Timers are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. In addition to aforementioned parameters, user defined Timer and State parameters can be used in a stateful DoFn. Timers and States are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. User defined State parameters can be used in a stateful DoFn. Timers aren’t implemented in the Go SDK yet; see more at Issue 22737. Once implemented, user defined Timer parameters can be used in a stateful DoFn. Timers and States are explained in more detail in the Timely [and Stateful] Processing with Apache Beam blog post

Timer and State. This feature isn’t yet implemented in the Typescript SDK, but we welcome contributions. In the meantime, Typescript pipelines wishing to use state and timers can do so using

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
34

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
35

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
36

4. 6. Composite transforms

Transforms can have a nested structure, where a complex transform performs multiple simpler transforms [such as more than one

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, or even other composite transforms]. These transforms are called composite transforms. Nesting multiple transforms inside a single composite transform can make your code more modular and easier to understand

The Beam SDK comes packed with many useful composite transforms. See the API reference pages for a list of transforms

  • Pre-written Beam transforms for Java
  • Pre-written Beam transforms for Python
  • Pre-written Beam transforms for Go

4. 6. 1. An example composite transform

The

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
51 transform in the WordCount example program is an example of a composite transform.
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
51 is a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass that consists of multiple nested transforms.

In its

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method, the The
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
51 transform applies the following transform operations.

  1. It applies a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    56 on the input
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of text lines, producing an output
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of individual words
  2. It applies the Beam SDK library transform
    public interface MyOptions extends PipelineOptions {
        String getInput[];
        void setInput[String input];
    
        String getOutput[];
        void setOutput[String output];
    }
    59 on the
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of words, producing a
    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 of key/value pairs. Each key represents a word in the text, and each value represents the number of times that word appeared in the original data

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
37

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
38

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
39

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
40

Note. Because

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
59 is itself a composite transform,
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
51 is also a nested composite transform

4. 6. 2. Tạo một biến đổi tổng hợp

A PTransform in the Typescript SDK is simply a function that accepts and returns

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
48s such as
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

To create your own composite transform, create a subclass of the

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 class and override the
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method to specify the actual processing logic. You can then use this transform just as you would a built-in transform from the Beam SDK

For the

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 class type parameters, you pass the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 types that your transform takes as input, and produces as output. To take multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as input, or produce multiple
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as output, use one of the multi-collection types for the relevant type parameter

To create your own composite

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 call the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84 method on the current pipeline scope variable. Transforms passed this new sub-
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
84 will be a part of the same composite
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78

To be able to re-use your Composite, build it inside a normal Go function or method. This function is passed a scope and input PCollections, and returns any output PCollections it produces. Note. Such functions cannot be passed directly to

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 functions

The following code sample shows how to declare a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 that accepts a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50s for input, and outputs a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
41

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
42

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
39

Within your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass, you’ll need to override the
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method. The
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method is where you add the processing logic for the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78. Your override of
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 must accept the appropriate type of input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as a parameter, and specify the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as the return value

The following code sample shows how to override

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 for the
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
90 class declared in the previous example

The following code sample shows how to call the

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
51 composite PTransform, adding it to your pipeline

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
44

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
42

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
46

As long as you override the

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method in your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 subclass to accept the appropriate input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73[s] and return the corresponding output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73[s], you can include as many transforms as you want. These transforms can include core transforms, composite transforms, or the transforms included in the Beam SDK libraries

Your composite

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78s can include as many transforms as you want. These transforms can include core transforms, other composite transforms, or the transforms included in the Beam SDK libraries. They can also consume and return as many
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as are necessary

Your composite transform’s parameters and return value must match the initial input type and final return type for the entire transform, even if the transform’s intermediate data changes type multiple times

Note. The

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
54 method of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 is not meant to be invoked directly by the user of a transform. Instead, you should call the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
31 method on the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 itself, with the transform as an argument. This allows transforms to be nested within the structure of your pipeline

4. 6. 3. PTransform Style Guide

The PTransform Style Guide contains additional information not included here, such as style guidelines, logging and testing guidance, and language-specific considerations. The guide is a useful starting point when you want to write new composite PTransforms

5. Pipeline I/O

Khi bạn tạo một đường dẫn, bạn thường cần đọc dữ liệu từ một số nguồn bên ngoài, chẳng hạn như tệp hoặc cơ sở dữ liệu. Likewise, you may want your pipeline to output its result data to an external storage system. Beam provides read and write transforms for a number of common data storage types. If you want your pipeline to read from or write to a data storage format that isn’t supported by the built-in transforms, you can implement your own read and write transforms

5. 1. Reading input data

Read transforms read data from an external source and return a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 representation of the data for use by your pipeline. You can use a read transform at any point while constructing your pipeline to create a new
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, though it will be most common at the start of your pipeline

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
47

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
48

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
49

5. 2. Writing output data

Write transforms write the data in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to an external data source. You will most often use write transforms at the end of your pipeline to output your pipeline’s final results. However, you can use a write transform to output a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's data at any point in your pipeline

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
50

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
51

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
52

5. 3. File-based input and output data

5. 3. 1. Reading from multiple locations

Many read transforms support reading from multiple input files matching a glob operator you provide. Note that glob operators are filesystem-specific and obey filesystem-specific consistency models. The following TextIO example uses a glob operator [

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
006] to read all matching input files that have prefix “input-” and the suffix “. csv” in the given location

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
53

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
54

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
55

To read data from disparate sources into a single

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, read each one independently and then use the transform to create a single
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

5. 3. 2. Writing to multiple output files

For file-based output data, write transforms write to multiple output files by default. When you pass an output file name to a write transform, the file name is used as the prefix for all output files that the write transform produces. You can append a suffix to each output file by specifying a suffix

The following write transform example writes multiple output files to a location. Each file has the prefix “numbers”, a numeric tag, and the suffix “. csv”

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
56

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
57

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
58

5. 4. Beam-provided I/O transforms

Xem trang Biến đổi I/O do Beam cung cấp để biết danh sách các biến đổi I/O hiện có

6. Schemas

Often, the types of the records being processed have an obvious structure. Common Beam sources produce JSON, Avro, Protocol Buffer, or database row objects; all of these types have well defined structures, structures that can often be determined by examining the type. Even within a SDK pipeline, Simple Java POJOs [or equivalent structures in other languages] are often used as intermediate types, and these also have a clear structure that can be inferred by inspecting the class. By understanding the structure of a pipeline’s records, we can provide much more concise APIs for data processing

6. 1. What is a schema?

Most structured records share some common characteristics

  • They can be subdivided into separate named fields. Fields usually have string names, but sometimes - as in the case of indexed tuples - have numerical indices instead
  • There is a confined list of primitive types that a field can have. These often match primitive types in most programming languages. int, long, string, etc
  • Often a field type can be marked as optional [sometimes referred to as nullable] or required

Often records have a nested structure. A nested structure occurs when a field itself has subfields so the type of the field itself has a schema. Fields that are array or map types is also a common feature of these structured records

For example, consider the following schema, representing actions in a fictitious e-commerce company

Purchase

Field NameField TypeuserIdSTRINGitemIdINT64shippingAddressROW[ShippingAddress]costINT64transactionsARRAY[ROW[Transaction]]

Địa chỉ giao hàng

Field NameField TypestreetAddressSTRINGcitySTRINGstatenullable STRINGcountrySTRINGpostCodeSTRING

Transaction

Field NameField TypebankSTRINGpurchaseAmountDOUBLE

Purchase event records are represented by the above purchase schema. Each purchase event contains a shipping address, which is a nested row containing its own schema. Each purchase also contains an array of credit-card transactions [a list, because a purchase might be split across multiple credit cards]; each item in the transaction list is a row with its own schema

Điều này cung cấp một mô tả trừu tượng về các loại liên quan, một loại được trừu tượng hóa khỏi bất kỳ ngôn ngữ lập trình cụ thể nào

Schemas provide us a type-system for Beam records that is independent of any specific programming-language type. There might be multiple Java classes that all have the same schema [for example a Protocol-Buffer class or a POJO class], and Beam will allow us to seamlessly convert between these types. Schemas also provide a simple way to reason about types across different programming-language APIs

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with a schema does not need to have a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 specified, as Beam knows how to encode and decode Schema rows; Beam uses a special coder to encode schema types

6. 2. Lược đồ cho các loại ngôn ngữ lập trình

While schemas themselves are language independent, they are designed to embed naturally into the programming languages of the Beam SDK being used. This allows Beam users to continue using native types while reaping the advantage of having Beam understand their element schemas

In Java you could use the following set of classes to represent the purchase schema. Beam will automatically infer the correct schema based on the members of the class

In Python you can use the following set of classes to represent the purchase schema. Beam will automatically infer the correct schema based on the members of the class

In Go, schema encoding is used by default for struct types, with Exported fields becoming part of the schema. Beam will automatically infer the schema based on the fields and field tags of the struct, and their order

In Typescript, JSON objects are used to represent schema’d data. Unfortunately type information in Typescript is not propagated to the runtime layer, so it needs to be manually specified in some places [e. g. when using cross-language pipelines]

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
59

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
60

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
61

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
62

Using JavaBean classes as above is one way to map a schema to Java classes. However multiple Java classes might have the same schema, in which case the different Java types can often be used interchangeably. Beam will add implicit conversions between types that have matching schemas. For example, the above

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
011 class has the same schema as the following class

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
63

So if we had two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
64

Then these two

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s would have the same schema, even though their Java types would be different. This means for example the following two code snippets are valid

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
65

and

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
66

Even though the in both cases the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 parameter differs from the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's Java type, since the schemas are the same Beam will automatically make the conversion. The built-in
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
016 transform can also be used to translate between Java types of equivalent schemas, as detailed below

6. 3. Schema definition

The schema for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 defines elements of that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as an ordered list of named fields. Each field has a name, a type, and possibly a set of user options. The type of a field can be primitive or composite. The following are the primitive types currently supported by Beam

TypeDescriptionBYTEAn 8-bit signed valueINT16A 16-bit signed valueINT32A 32-bit signed valueINT64A 64-bit signed valueDECIMALAn arbitrary-precision decimal typeFLOATA 32-bit IEEE 754 floating point numberDOUBLEA 64-bit IEEE 754 floating point numberSTRINGA stringDATETIMEA timestamp represented as milliseconds since the epochBOOLEANA boolean valueBYTESA raw byte array

A field can also reference a nested schema. In this case, the field will have type ROW, and the nested schema will be an attribute of this field type

Three collection types are supported as field types. ARRAY, ITERABLE and MAP

  • ARRAY This represents a repeated value type, where the repeated elements can have any supported type. Arrays of nested rows are supported, as are arrays of arrays
  • ITERABLE Điều này rất giống với kiểu mảng, nó đại diện cho một giá trị được lặp lại, nhưng một giá trị trong đó danh sách đầy đủ các mục không được biết cho đến khi được lặp lại. This is intended for the case where an iterable might be larger than the available memory, and backed by external storage [for example, this can happen with the iterable returned by a
    from apache_beam.options.pipeline_options import PipelineOptions
    
    beam_options = PipelineOptions[]
    14]. The repeated elements can have any supported type
  • MAP This represents an associative map from keys to values. All schema types are supported for both keys and values. Values that contain map types cannot be used as keys in any grouping operation

6. 4. Logical types

Users can extend the schema type system to add custom logical types that can be used as a field. A logical type is identified by a unique identifier and an argument. A logical type also specifies an underlying schema type to be used for storage, along with conversions to and from that type. As an example, a logical union can always be represented as a row with nullable fields, where the user ensures that only one of those fields is ever set at a time. However this can be tedious and complex to manage. The OneOf logical type provides a value class that makes it easier to manage the type as a union, while still using a row with nullable fields as its underlying storage. Each logical type also has a unique identifier, so they can be interpreted by other languages as well. More examples of logical types are listed below

6. 4. 1. Defining a logical type

To define a logical type you must specify a Schema type to be used to represent the underlying type as well as a unique identifier for that type. A logical type imposes additional semantics on top a schema type. For example, a logical type to represent nanosecond timestamps is represented as a schema containing an INT64 and an INT32 field. This schema alone does not say anything about how to interpret this type, however the logical type tells you that this represents a nanosecond timestamp, with the INT64 field representing seconds and the INT32 field representing nanoseconds

Logical types are also specified by an argument, which allows creating a class of related types. For example, a limited-precision decimal type would have an integer argument indicating how many digits of precision are represented. The argument is represented by a schema type, so can itself be a complex type

In Java, a logical type is specified as a subclass of the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
020 class. A custom Java class can be specified to represent the logical type and conversion functions must be supplied to convert back and forth between this Java class and the underlying Schema type representation. For example, the logical type representing nanosecond timestamp might be implemented as follows

In Go, a logical type is specified with a custom implementation of the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
021 interface. For example, the logical type provider representing nanosecond timestamps might be implemented as follows

In Typescript, a logical type defined by the LogicalTypeInfo interface which associates a logical type’s URN with its representation and its conversion to and from this representation

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
67

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
68

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
69

6. 4. 2. Useful logical types

Currently the Python SDK provides minimal convenience logical types, other than to handle

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
022

Currently the Go SDK provides minimal convenience logical types, other than to handle additional integer primitives, and

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
023

EnumerationType

This convenience builder doesn’t yet exist for the Python SDK

This convenience builder doesn’t yet exist for the Go SDK

This logical type allows creating an enumeration type consisting of a set of named constants

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
70

The value of this field is stored in the row as an INT32 type, however the logical type defines a value type that lets you access the enumeration either as a string or a value. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
71

Given a row object with an enumeration field, you can also extract the field as the enumeration value

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
72

Automatic schema inference from Java POJOs and JavaBeans automatically converts Java enums to EnumerationType logical types

OneOfType

This convenience builder doesn’t yet exist for the Python SDK

This convenience builder doesn’t yet exist for the Go SDK

OneOfType allows creating a disjoint union type over a set of schema fields. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
73

The value of this field is stored in the row as another Row type, where all the fields are marked as nullable. The logical type however defines a Value object that contains an enumeration value indicating which field was set and allows getting just that field

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
74

In the above example we used the field names in the switch statement for clarity, however the enum integer values could also be used

6. 5. Creating Schemas

In order to take advantage of schemas, your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s must have a schema attached to it. Often, the source itself will attach a schema to the PCollection. For example, when using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
025 to read Avro files, the source can automatically infer a Beam schema from the Avro schema and attach that to the Beam
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. However not all sources produce schemas. In addition, often Beam pipelines have intermediate stages and types, and those also can benefit from the expressiveness of schemas

6. 5. 1. Inferring schemas

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

Unfortunately, Beam is unable to access Typescript’s type information at runtime. Schemas must be manually declared with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
027. On the other hand, schema-aware operations such as
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 can be used without an explicit schema declared

Beam is able to infer schemas from a variety of common Java types. The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
029 annotation can be used to tell Beam to infer schemas from a specific type. Chú thích lấy một đối số là
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
030 và các lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
030 đã được tích hợp sẵn cho các loại Java phổ biến. The
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
032 can also be invoked programmatically for cases where it is not practical to annotate the Java type itself

Java POJOs

A POJO [Plain Old Java Object] is a Java object that is not bound by any restriction other than the Java Language Specification. A POJO can contain member variables that are primitives, that are other POJOs, or are collections maps or arrays thereof. POJOs do not have to extend prespecified classes or extend any specific interfaces

If a POJO class is annotated with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
033, Beam will automatically infer a schema for this class. Nested classes are supported as are classes with
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
83, array, and
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
67 fields

For example, annotating the following class tells Beam to infer a schema from this POJO class and apply it to any

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
036

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
75

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
037 annotation tells Beam that this constructor can be used to create instances of TransactionPojo, assuming that constructor parameters have the same names as the field names.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
037 can also be used to annotate static factory methods on the class, allowing the constructor to remain private. If there is no
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
037 annotation then all the fields must be non-final and the class must have a zero-argument constructor

There are a couple of other useful annotations that affect how Beam infers schemas. By default the schema field names inferred will match that of the class field names. However

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 can be used to specify a different name to be used for the schema field.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
041 can be used to mark specific class fields as excluded from the inferred schema. For example, it’s common to have ephemeral fields in a class that should not be included in a schema [e. g. caching the hash value to prevent expensive recomputation of the hash], and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
041 can be used to exclude these fields. Note that ignored fields will not be included in the encoding of these records

In some cases it is not convenient to annotate the POJO class, for example if the POJO is in a different package that is not owned by the Beam pipeline author. In these cases the schema inference can be triggered programmatically in pipeline’s main function as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
76

Java Beans

Java Beans are a de-facto standard for creating reusable property classes in Java. While the full standard has many characteristics, the key ones are that all properties are accessed via getter and setter classes, and the name format for these getters and setters is standardized. A Java Bean class can be annotated with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
043 and Beam will automatically infer a schema for this class. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
77

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
037 annotation can be used to specify a constructor or a static factory method, in which case the setters and zero-argument constructor can be omitted

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
78

Có thể sử dụng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
041 để thay đổi lược đồ được suy ra, giống như với các lớp POJO

AutoValue

Java value classes are notoriously difficult to generate correctly. There is a lot of boilerplate you must create in order to properly implement a value class. AutoValue là một thư viện phổ biến để dễ dàng tạo các lớp như vậy bằng cách triển khai một lớp cơ sở trừu tượng đơn giản

Beam có thể suy ra lược đồ từ lớp AutoValue. Ví dụ

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
79

This is all that’s needed to generate a simple AutoValue class, and the above

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
029 annotation tells Beam to infer a schema from it. This also allows AutoValue elements to be used inside of
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
040 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
041 can be used to alter the schema inferred

Beam has a few different mechanisms for inferring schemas from Python code

NamedTuple classes

A class is a Python class that wraps a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
44, assigning a name to each element and restricting it to a particular type. Beam will automatically infer the schema for PCollections with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
052 output types. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
80

beam. Row and Select

There are also methods for creating ad-hoc schema declarations. First, you can use a lambda that returns instances of

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
053

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
81

Sometimes it can be more concise to express the same logic with the transform

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
82

Note that these declaration don’t include any specific information about the types of the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
055 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
056 fields, so Beam will attempt to infer type information. If it’s unable to it will fall back to the generic type
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
057. Sometimes this is not ideal, you can use casts to make sure Beam correctly infers types with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
053 or with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
054

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
83

Beam currently only infers schemas for exported fields in Go structs

Structs

Beam will automatically infer schemas for all Go structs used as PCollection elements, and default to encoding them using schema encoding

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
84

Unexported fields are ignored, and cannot be automatically inferred as part of the schema. Fields of type func, channel, unsafe. Pointer, or uintptr will be ignored by inference. Fields of interface types are ignored, unless a schema provider is registered for them

By default, schema field names will match the exported struct field names. In the above example, “Bank” and “PurchaseAmount” are the schema field names. A schema field name can be overridden with a struct tag for the field

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
85

Overriding schema field names is useful for compatibility cross language transforms, as schema fields may have different requirements or restrictions from Go exported fields

6. 6. Using Schema Transforms

A schema on a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 enables a rich variety of relational transforms. Thực tế là mỗi bản ghi bao gồm các trường được đặt tên cho phép các tập hợp đơn giản và dễ đọc, tham chiếu các trường theo tên, tương tự như các tập hợp trong biểu thức SQL

Beam does not yet support Schema transforms natively in Go. However, it will be implemented with the following behavior

6. 6. 1. Field selection syntax

The advantage of schemas is that they allow referencing of element fields by name. Beam provides a selection syntax for referencing fields, including nested and repeated fields. This syntax is used by all of the schema transforms when referencing the fields they operate on. The syntax can also be used inside of a DoFn to specify which schema fields to process

Addressing fields by name still retains type safety as Beam will check that schemas match at the time the pipeline graph is constructed. If a field is specified that does not exist in the schema, the pipeline will fail to launch. In addition, if a field is specified with a type that does not match the type of that field in the schema, the pipeline will fail to launch

The following characters are not allowed in field names. . * [ ] { }

Top-level fields

In order to select a field at the top level of a schema, the name of the field is specified. For example, to select just the user ids from a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of purchases one would write [using the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
054 transform]

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
86

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
87

Nested fields

Support for Nested fields hasn’t been developed for the Python SDK yet

Support for Nested fields hasn’t been developed for the Go SDK yet

Individual nested fields can be specified using the dot operator. For example, to select just the postal code from the shipping address one would write

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
88

Wildcards

Support for wildcards hasn’t been developed for the Python SDK yet

Support for wildcards hasn’t been developed for the Go SDK yet

The * operator can be specified at any nesting level to represent all fields at that level. For example, to select all shipping-address fields one would write

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
89

Arrays

An array field, where the array element type is a row, can also have subfields of the element type addressed. When selected, the result is an array of the selected subfield type. For example

Support for Array fields hasn’t been developed for the Python SDK yet

Support for Array fields hasn’t been developed for the Go SDK yet

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
90

Will result in a row containing an array field with element-type string, containing the list of banks for each transaction

While the use of [] brackets in the selector is recommended, to make it clear that array elements are being selected, they can be omitted for brevity. In the future, array slicing will be supported, allowing selection of portions of the array

Maps

A map field, where the value type is a row, can also have subfields of the value type addressed. When selected, the result is a map where the keys are the same as in the original map but the value is the specified type. Similar to arrays, the use of {} curly brackets in the selector is recommended, to make it clear that map value elements are being selected, they can be omitted for brevity. In the future, map key selectors will be supported, allowing selection of specific keys from the map. For example, given the following schema

PurchasesByType

Field NameField TypepurchasesMAP{STRING, ROW{PURCHASE}

Sau đây

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
91

Hỗ trợ cho các trường Bản đồ chưa được phát triển cho Python SDK

Hỗ trợ cho các trường Bản đồ chưa được phát triển cho Go SDK

Sẽ dẫn đến một hàng chứa trường bản đồ với chuỗi loại khóa và chuỗi loại giá trị. Bản đồ đã chọn sẽ chứa tất cả các khóa từ bản đồ gốc và các giá trị sẽ là userId có trong bản ghi mua hàng

Mặc dù nên sử dụng dấu ngoặc {} trong bộ chọn, nhưng để làm rõ rằng các phần tử giá trị bản đồ đang được chọn, chúng có thể được bỏ qua cho ngắn gọn. Trong tương lai, tính năng cắt bản đồ sẽ được hỗ trợ, cho phép chọn các phím cụ thể từ bản đồ

6. 6. 2. Biến đổi lược đồ

Beam cung cấp một tập hợp các biến đổi hoạt động tự nhiên trên các lược đồ. Các biến đổi này rất biểu cảm, cho phép lựa chọn và tổng hợp theo các trường lược đồ được đặt tên. Sau đây là một số ví dụ về biến đổi lược đồ hữu ích

Chọn đầu vào

Thông thường, một phép tính chỉ quan tâm đến một tập hợp con các trường trong đầu vào

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
054 cho phép một người dễ dàng chỉ chiếu ra các trường quan tâm. Kết quả
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 có một lược đồ chứa từng trường được chọn dưới dạng trường cấp cao nhất. Có thể chọn cả trường cấp cao nhất và trường lồng nhau. Ví dụ: trong lược đồ Mua hàng, người ta chỉ có thể chọn các trường userId và streetAddress như sau

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
92

Support for Nested fields hasn’t been developed for the Python SDK yet

Support for Nested fields hasn’t been developed for the Go SDK yet

Kết quả

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 sẽ có lược đồ sau

Field NameField TypeuserIdSTRINGstreetAddressSTRING

Điều này cũng đúng với các lựa chọn ký tự đại diện. Sau đây

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
93

Support for Wildcards hasn’t been developed for the Python SDK yet

Support for Wildcards hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypeuserIdSTRINGstreetAddressSTRINGcitySTRINGstatenullable STRINGcountrySTRINGpostCodeSTRING

When selecting fields nested inside of an array, the same rule applies that each selected field appears separately as a top-level field in the resulting row. This means that if multiple fields are selected from the same nested row, each selected field will appear as its own array field. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
94

Support for nested fields hasn’t been developed for the Python SDK yet

Support for nested fields hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypebankARRAY[STRING]purchaseAmountARRAY[DOUBLE]

Wildcard selections are equivalent to separately selecting each field

Selecting fields nested inside of maps have the same semantics as arrays. If you select multiple fields from a map , then each selected field will be expanded to its own map at the top level. This means that the set of map keys will be copied, once for each selected field

Sometimes different nested rows will have fields with the same name. Selecting multiple of these fields would result in a name conflict, as all selected fields are put in the same row schema. When this situation arises, the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
067 builder method can be used to provide an alternate name for the selected field

Another use of the Select transform is to flatten a nested schema into a single flat schema. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
95

Support for nested fields hasn’t been developed for the Python SDK yet

Support for nested fields hasn’t been developed for the Go SDK yet

Will result in the following schema

Field NameField TypeuserIdSTRINGitemIdSTRINGshippingAddress_streetAddressSTRINGshippingAddress_citynullable STRINGshippingAddress_stateSTRINGshippingAddress_countrySTRINGshippingAddress_postCodeSTRINGcostCentsINT64transactions_bankARRAY[STRING]transactions_purchaseAmountARRAY[DOUBLE]

Grouping aggregations

The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
068 transform allows simply grouping data by any number of fields in the input schema, applying aggregations to those groupings, and storing the result of those aggregations in a new schema field. The output of the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
068 transform has a schema with one field corresponding to each aggregation performed

The

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 transform allows simply grouping data by any number of fields in the input schema, applying aggregations to those groupings, and storing the result of those aggregations in a new schema field. The output of the
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 transform has a schema with one field corresponding to each aggregation performed

The simplest usage of

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
068 specifies no aggregations, in which case all inputs matching the provided set of fields are grouped together into an
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
073 field. For example

The simplest usage of

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
87 specifies no aggregations, in which case all inputs matching the provided set of fields are grouped together into an
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
073 field. For example

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
96

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
97

Support for schema-aware grouping hasn’t been developed for the Go SDK yet

The output schema of this is

Field NameField TypekeyROW{userId. STRING, bank. STRING}valuesITERABLE[ROW[Purchase]]

The key field contains the grouping key and the values field contains a list of all the values that matched that key

The names of the key and values fields in the output schema can be controlled using this withKeyField and withValueField builders, as follows

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
98

It is quite common to apply one or more aggregations to the grouped result. Each aggregation can specify one or more fields to aggregate, an aggregation function, and the name of the resulting field in the output schema. For example, the following application computes three aggregations grouped by userId, with all aggregations represented in a single output schema

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
99

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
00

Support for schema-aware grouping hasn’t been developed for the Go SDK yet

The result of this aggregation will have the following schema

Field NameField TypekeyROW{userId. STRING}valueROW{numPurchases. INT64, totalSpendCents. INT64, topPurchases. ARRAY[INT64]}

Often

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
076 will be use to flatten the result into a non-nested, flat schema

Joins

Beam supports equijoins on schema

const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
37 - namely joins where the join condition depends on the equality of a subset of fields. For example, the following examples uses the Purchases schema to join transactions with the reviews that are likely associated with that transaction [both the user and product match that in the transaction]. This is a “natural join” - one in which the same field names are used on both the left-hand and right-hand sides of the join - and is specified with the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
078 keyword

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
01

The resulting schema is the following

Field NameField TypelhsROW{Transaction}rhsROW{Review}

Each resulting row contains one Transaction and one Review that matched the join condition

If the fields to match in the two schemas have different names, then the on function can be used. For example, if the Review schema named those fields differently than the Transaction schema, then we could write the following

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
02

In addition to inner joins, the Join transform supports full outer joins, left outer joins, and right outer joins

Complex joins

While most joins tend to be binary joins - joining two inputs together - sometimes you have more than two input streams that all need to be joined on a common key. The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
079 transform allows joining multiple
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
37 together based on equality of schema fields. Each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can be marked as required or optional in the final join record, providing a generalization of outer joins to joins with greater than two input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. Đầu ra có thể được mở rộng tùy chọn - cung cấp các bản ghi được nối riêng lẻ, như trong biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
083. The output can also be processed in unexpanded format - providing the join key along with Iterables of all records from each input that matched that key

Support for joins hasn’t been developed for the Python SDK yet

Support for joins hasn’t been developed for the Go SDK yet

Filtering events

The

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
71 transform can be configured with a set of predicates, each one based one specified fields. Only records for which all predicates return true will pass the filter. For example the following

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
03

Will produce all purchases made from Germany with a purchase price of greater than twenty cents

Adding fields to a schema

The AddFields transform can be used to extend a schema with new fields. Các hàng đầu vào sẽ được mở rộng sang lược đồ mới bằng cách chèn các giá trị null cho các trường mới, mặc dù có thể chỉ định các giá trị mặc định thay thế; . Có thể thêm các trường con lồng nhau bằng cách sử dụng cú pháp chọn trường, bao gồm các trường lồng nhau bên trong các mảng hoặc giá trị bản đồ

For example, the following application

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
04

Results in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with an expanded schema. All of the rows and fields of the input, but also with the specified fields added to the schema. All resulting rows will have null values filled in for the timeOfDaySeconds and the shippingAddress. deliveryNotes fields, and a false value filled in for the transactions. isFlagged field

Removing fields from a schema

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
086 allows specific fields to be dropped from a schema. Input rows will have their schemas truncated, and any values for dropped fields will be removed from the output. Nested fields can also be dropped using the field selection syntax

For example, the following snippet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
05

Results in a copy of the input with those two fields and their corresponding values removed

Renaming schema fields

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
087 allows specific fields in a schema to be renamed. The field values in input rows are left unchanged, only the schema is modified. This transform is often used to prepare records for output to a schema-aware sink, such as an RDBMS, to make sure that the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 schema field names match that of the output. It can also be used to rename fields generated by other transforms to make them more usable [similar to SELECT AS in SQL]. Nested fields can also be renamed using the field-selection syntax

For example, the following snippet

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
06

Results in the same set of unmodified input elements, however the schema on the PCollection has been changed to rename userId to userIdentifier and shippingAddress. streetAddress to shippingAddress. street

Converting between types

As mentioned, Beam can automatically convert between different Java types, as long as those types have equivalent schemas. One way to do this is by using the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
016 transform, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
07

Beam will validate that the inferred schema for

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
090 matches that of the input
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, and will then cast to a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
092

Since the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
093 class can support any schema, any
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with schema can be cast to a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 of rows, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
08

If the source type is a single-field schema, Convert will also convert to the type of the field if asked, effectively unboxing the row. For example, give a schema with a single INT64 field, the following will convert it to a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
096

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
09

In all cases, type checking is done at pipeline graph construction, and if the types do not match the schema then the pipeline will fail to launch

6. 6. 3. Lược đồ trong ParDo

A

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with a schema can apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, just like any other
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. However the Beam runner is aware of schemas when applying a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, which enables additional functionality

Input conversion

Beam does not yet support input conversion in Go

Since Beam knows the schema of the source

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, it can automatically convert the elements to any Java type for which a matching schema is known. For example, using the above-mentioned Transaction schema, say we have the following
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
10

If there were no schema, then the applied

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 would have to accept an element of type
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
104. However since there is a schema, you could apply the following DoFn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
11

Even though the

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
23 parameter does not match the Java type of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, since it has a matching schema Beam will automatically convert elements. If the schema does not match, Beam will detect this at graph-construction time and will fail the job with a type error

Since every schema can be represented by a Row type, Row can also be used here

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
12

Input selection

Since the input has a schema, you can also automatically select specific fields to process in the DoFn

Given the above purchases

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, say you want to process just the userId and the itemId fields. You can do these using the above-described selection expressions, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
13

You can also select nested fields, as follows

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
14

For more information, see the section on field-selection expressions. When selecting subschemas, Beam will automatically convert to any matching schema type, just like when reading the entire row

7. Data encoding and type safety

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

When Beam runners execute your pipeline, they often need to materialize the intermediate data in your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, which requires converting elements to and from byte strings. The Beam SDKs use objects called
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66s to describe how the elements of a given
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 may be encoded and decoded

Note that coders are unrelated to parsing or formatting data when interacting with external data sources or sinks. Such parsing or formatting should typically be done explicitly, using transforms such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 or
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
66

In the Beam SDK for Java, the type

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 provides the methods required for encoding and decoding data. The SDK for Java provides a number of Coder subclasses that work with a variety of standard Java types, such as Integer, Long, Double, StringUtf8 and more. You can find all of the available Coder subclasses in the Coder package

In the Beam SDK for Python, the type

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 provides the methods required for encoding and decoding data. The SDK for Python provides a number of Coder subclasses that work with a variety of standard Python types, such as primitive types, Tuple, Iterable, StringUtf8 and more. You can find all of the available Coder subclasses in the apache_beam. coders package

Standard Go types like

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
116
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
117,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
118, and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 and more are coded using builtin coders. Structs and pointers to structs default using Beam Schema Row encoding. However, users can build and register custom coders with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
120. You can find available Coder functions in the coder package

Standard Typescript types like

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
121,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
122 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96 and more are coded using builtin coders. Json objects and arrays are encoded via a BSON encoding. For these types, coders need not be specified unless interacting with cross-language transforms. Users can build custom coders by extending
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
124 for use with
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
125, but generally logical types are preferred for this case

Note that coders do not necessarily have a 1. 1 relationship with types. For example, the Integer type can have multiple valid coders, and input and output data can use different Integer coders. A transform might have Integer-typed input data that uses BigEndianIntegerCoder, and Integer-typed output data that uses VarIntCoder

7. 1. Specifying coders

The Beam SDKs require a coder for every

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 in your pipeline. In most cases, the Beam SDK is able to automatically infer a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 based on its element type or the transform that produces it, however, in some cases the pipeline author will need to specify a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 explicitly, or develop a
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for their custom type

You can explicitly set the coder for an existing

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
132. Note that you cannot call
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
133 on a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that has been finalized [e. g. by calling
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
135 on it]

You can get the coder for an existing

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
137. This method will fail with an
--=
26 if a coder has not been set and cannot be inferred for the given
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Beam SDKs use a variety of mechanisms when attempting to automatically infer the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Each pipeline object has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142. The
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 represents a mapping of Java types to the default coders that the pipeline should use for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of each type

The Beam SDK for Python has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 that represents a mapping of Python types to the default coder that should be used for
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s of each type

The Beam SDK for Go allows users to register default coder implementations with

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
120

By default, the Beam SDK for Java automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 produced by a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
78 using the type parameter from the transform’s function object, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example, a
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
153 function object accepts an input element of type
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
00 and produces an output element of type
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
50. In such a case, the SDK for Java will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
157 [in the default pipeline
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142, this is
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
159]

By default, the Beam SDK for Python automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 using the typehints from the transform’s function object, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 with the typehints
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
165 and
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
166 accepts an input element of type int and produces an output element of type str. In such a case, the Beam SDK for Python will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [in the default pipeline
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142, this is
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
170]

By default, the Beam SDK for Go automatically infers the

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the elements of an output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by the output of the transform’s function object, such as a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. In the case of
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, for example a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 with the parameters of
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
176 accepts an input element of type
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01 and produces an output element of type
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96. In such a case, the Beam SDK for Go will automatically infer the default
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the output
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to be the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
181 coder

Note. If you create your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 from in-memory data by using the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 transform, you cannot rely on coder inference and default coders.
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
94 does not have access to any typing information for its arguments, and may not be able to infer a coder if the argument list contains a value whose exact run-time class doesn’t have a default coder registered

Khi sử dụng _______9_______94, cách đơn giản nhất để đảm bảo rằng bạn có bộ mã hóa chính xác là gọi ___54_______186 khi bạn áp dụng phép biến đổi _________94

7. 2. Default coders and the CoderRegistry

Each Pipeline object has a

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 object, which maps language types to the default coder the pipeline should use for those types. You can use the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 yourself to look up the default coder for a given type, or to register a new default coder for a given type

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 contains a default mapping of coders to standard JavaPython types for any pipeline you create using the Beam SDK for JavaPython . The following table shows the standard mapping.

Java TypeDefault CoderDoubleDoubleCoderInstantInstantCoderIntegerVarIntCoderIterableIterableCoderKVKvCoderListListCoderMapMapCoderLongVarLongCoderStringStringUtf8CoderTableRowTableRowJsonCoderVoidVoidCoderbyte[ ]ByteArrayCoderTimestampedValueTimestampedValueCoder

Python TypeDefault CoderintVarIntCoderfloatFloatCoderstrBytesCoderbytesStrUtf8CoderTupleTupleCoder

7. 2. 1. Looking up a default coder

You can use the method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
191 to determine the default Coder for a Java type. You can access the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 for a given pipeline by using the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
193. This allows you to determine [or set] the default Coder for a Java type on a per-pipeline basis. i. e. “for this pipeline, verify that Integer values are encoded using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
194. ”

You can use the method

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
195 to determine the default Coder for a Python type. You can use
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
196 to access the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142. This allows you to determine [or set] the default Coder for a Python type

You can use the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
198 function to determine the default Coder for a Go type

7. 2. 2. Setting the default coder for a type

To set the default Coder for a JavaPython type for a particular pipeline, you obtain and modify the pipeline’s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142. You use the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
193
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
196
to get the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
142 object, and then use the method
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
203
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
204
to register a new
PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
66 for the target type.

To set the default Coder for a Go type you use the function

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
120 to register a encoder and decoder functions for the target type. However, built in types like
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
96,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
117, etc cannot have their coders override

The following example code demonstrates how to set a default Coder, in this case

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
194, for Integerint values for a pipeline.

The following example code demonstrates how to set a custom Coder for

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
211 elements

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
15

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
16

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
17

7. 2. 3. Chú thích một loại dữ liệu tùy chỉnh với một bộ mã hóa mặc định

Nếu chương trình đường ống của bạn xác định loại dữ liệu tùy chỉnh, bạn có thể sử dụng chú thích

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
212 để chỉ định bộ mã hóa sẽ sử dụng với loại đó. Theo mặc định, Beam sẽ sử dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
213 sử dụng tuần tự hóa Java, nhưng nó có nhược điểm

  1. Nó không hiệu quả về kích thước và tốc độ mã hóa. Xem phần so sánh các phương thức tuần tự hóa Java này

  2. Nó không xác định. nó có thể tạo ra các mã hóa nhị phân khác nhau cho hai đối tượng tương đương

    Đối với các cặp khóa/giá trị, tính chính xác của các thao tác dựa trên khóa [GroupByKey, Combine] và Trạng thái trên mỗi khóa phụ thuộc vào việc có một bộ mã hóa xác định cho khóa

Bạn có thể sử dụng chú thích

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
212 để đặt mặc định mới như sau

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
18

Nếu bạn đã tạo một bộ mã hóa tùy chỉnh để phù hợp với loại dữ liệu của mình và bạn muốn sử dụng chú thích

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
212, thì lớp bộ mã hóa của bạn phải triển khai một phương thức xuất xưởng tĩnh
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
216

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
19

The Beam SDK for PythonGo does not support annotating data types with a default coder. Nếu bạn muốn đặt bộ mã hóa mặc định, hãy sử dụng phương pháp được mô tả trong phần trước, Đặt bộ mã hóa mặc định cho loại.

8. Windowing

Windowing subdivides a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 according to the timestamps of its individual elements. Transforms that aggregate multiple elements, such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, work implicitly on a per-window basis — they process each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 as a succession of multiple, finite windows, though the entire collection itself may be of unbounded size

A related concept, called triggers, determines when to emit the results of aggregation as unbounded data arrives. You can use triggers to refine the windowing strategy for your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Triggers allow you to deal with late-arriving data or to provide early results. See the section for more information

8. 1. Windowing basics

Some Beam transforms, such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, group multiple elements by a common key. Ordinarily, that grouping operation groups all of the elements that have the same key within the entire data set. With an unbounded data set, it is impossible to collect all of the elements, since new elements are constantly being added and may be infinitely many [e. g. streaming data]. If you are working with unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s, windowing is especially useful

In the Beam model, any

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 [including unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s] can be subdivided into logical windows. Each element in a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is assigned to one or more windows according to the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's windowing function, and each individual window contains a finite number of elements. Grouping transforms then consider each
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73's elements on a per-window basis.
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, for example, implicitly groups the elements of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by key and window

Caution. Beam’s default windowing behavior is to assign all elements of a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 to a single, global window and discard late data, even for unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. Before you use a grouping transform such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 on an unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, you must do at least one of the following

  • Set a non-global windowing function. See
  • Set a non-default . This allows the global window to emit results under other conditions, since the default windowing behavior [waiting for all data to arrive] will never occur

If you don’t set a non-global windowing function or a non-default trigger for your unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 and subsequently use a grouping transform such as
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 or
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15, your pipeline will generate an error upon construction and your job will fail

8. 1. 1. Windowing constraints

After you set the windowing function for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, the elements’ windows are used the next time you apply a grouping transform to that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Window grouping occurs on an as-needed basis. Nếu bạn đặt chức năng tạo cửa sổ bằng cách sử dụng biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241, thì mỗi phần tử được gán cho một cửa sổ, nhưng các cửa sổ đó không được xem xét cho đến khi
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 hoặc
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15 tổng hợp trên một cửa sổ và phím. This can have different effects on your pipeline. Consider the example pipeline in the figure below

Figure 3. Pipeline applying windowing

In the above pipeline, we create an unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading a set of key/value pairs using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
245, and then apply a windowing function to that collection using the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 transform. We then apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 to the collection, and then later group the result of that
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 using
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14. The windowing function has no effect on the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform, because the windows are not actually used until they’re needed for the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14. Subsequent transforms, however, are applied to the result of the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 – data is grouped by both key and window

8. 1. 2. Windowing with bounded PCollections

You can use windowing with fixed-size data sets in bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73s. However, note that windowing considers only the implicit timestamps attached to each element of a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, and data sources that create fixed data sets [such as
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
255] assign the same timestamp to every element. This means that all the elements are by default part of a single, global window

To use windowing with fixed data sets, you can assign your own timestamps to each element. To assign timestamps to elements, use a

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform with a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 that outputs each element with a new timestamp [for example, the WithTimestamps transform in the Beam SDK for Java]

To illustrate how windowing with a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can affect how your pipeline processes data, consider the following pipeline

Figure 4.

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 without windowing, on a bounded collection

In the above pipeline, we create a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading lines from a file using
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
255. We then group the collection using
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14, and apply a
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform to the grouped
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. In this example, the
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 creates a collection of unique keys, and then
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 gets applied exactly once per key

Note that even if you don’t set a windowing function, there is still a window – all elements in your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 are assigned to a single global window

Now, consider the same pipeline, but using a windowing function

Figure 5.

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 with windowing, on a bounded collection

As before, the pipeline creates a bounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by reading lines from a file. We then set a for that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 transform groups the elements of the
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by both key and window, based on the windowing function. The subsequent
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 transform gets applied multiple times per key, once for each window

8. 2. Provided windowing functions

You can define different kinds of windows to divide the elements of your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Beam provides several windowing functions, including

  • Fixed Time Windows
  • Sliding Time Windows
  • Per-Session Windows
  • Single Global Window
  • Calendar-based Windows [not supported by the Beam SDK for Python or Go]

You can also define your own

--=
42 if you have a more complex need

Note that each element can logically belong to more than one window, depending on the windowing function you use. Sliding time windowing, for example, can create overlapping windows wherein a single element can be assigned to multiple windows. However, each element in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can only be in one window, so if an element is assigned to multiple windows, the element is conceptually duplicated into each of the windows and each element is identical except for its window

8. 2. 1. Fixed time windows

The simplest form of windowing is using fixed time windows. given a timestamped

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 which might be continuously updating, each window might capture [for example] all elements with timestamps that fall into a 30 second interval

A fixed time window represents a consistent duration, non overlapping time interval in the data stream. Consider windows with a 30 second duration. all of the elements in your unbounded

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 with timestamp values from 0. 00. 00 up to [but not including] 0. 00. 30 belong to the first window, elements with timestamp values from 0. 00. 30 up to [but not including] 0. 01. 00 belong to the second window, and so on

Figure 6. Fixed time windows, 30s in duration

8. 2. 2. Sliding time windows

A sliding time window also represents time intervals in the data stream; however, sliding time windows can overlap. For example, each window might capture 60 seconds worth of data, but a new window starts every 30 seconds. The frequency with which sliding windows begin is called the period. Therefore, our example would have a window duration of 60 seconds and a period of 30 seconds

Because multiple windows overlap, most elements in a data set will belong to more than one window. This kind of windowing is useful for taking running averages of data; using sliding time windows, you can compute a running average of the past 60 seconds’ worth of data, updated every 30 seconds, in our example

Figure 7. Sliding time windows, with 1 minute window duration and 30s window period

8. 2. 3. Session windows

A session window function defines windows that contain elements that are within a certain gap duration of another element. Session windowing applies on a per-key basis and is useful for data that is irregularly distributed with respect to time. For example, a data stream representing user mouse activity may have long periods of idle time interspersed with high concentrations of clicks. If data arrives after the minimum specified gap duration time, this initiates the start of a new window

Figure 8. Session windows, with a minimum gap duration. Lưu ý cách mỗi khóa dữ liệu có các cửa sổ khác nhau, theo phân phối dữ liệu của nó

8. 2. 4. The single global window

By default, all data in a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 is assigned to the single global window, and late data is discarded. If your data set is of a fixed size, you can use the global window default for your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

You can use the single global window if you are working with an unbounded data set [e. g. from a streaming data source] but use caution when applying aggregating transforms such as

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
14 and
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
15. The single global window with a default trigger generally requires the entire data set to be available before processing, which is not possible with continuously updating data. To perform aggregations on an unbounded
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 that uses global windowing, you should specify a non-default trigger for that
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

8. 3. Setting your PCollection’s windowing function

You can set the windowing function for a

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 by applying the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 transform. When you apply the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 transform, you must provide a
--=
42. The
--=
42 determines the windowing function your
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 will use for subsequent grouping transforms, such as a fixed or sliding time window

When you set a windowing function, you may also want to set a trigger for your

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. The trigger determines when each individual window is aggregated and emitted, and helps refine how the windowing function performs with respect to late data and computing early results. See the section for more information

8. 3. 1. Fixed-time windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into fixed windows, each 60 seconds in length

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
20

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
21

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
22

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
23

8. 3. 2. Sliding time windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into sliding time windows. Each window is 30 seconds in length, and a new window begins every five seconds

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
24

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
25

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
26

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
27

8. 3. 3. Session windows

The following example code shows how to apply

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241 to divide a
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 into session windows, where each session must be separated by a time gap of at least 10 minutes [600 seconds]

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
28

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
29

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
30

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
31

Lưu ý rằng các phiên là theo từng khóa — mỗi khóa trong bộ sưu tập sẽ có các nhóm phiên riêng tùy thuộc vào phân phối dữ liệu

8. 3. 4. Cửa sổ toàn cầu duy nhất

Nếu

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn bị giới hạn [kích thước cố định], bạn có thể gán tất cả các phần tử cho một cửa sổ chung duy nhất. Mã ví dụ sau đây cho biết cách đặt một cửa sổ chung cho một
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
32

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
33

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
34

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
35

8. 4. Hình mờ và dữ liệu muộn

Trong bất kỳ hệ thống xử lý dữ liệu nào, có một độ trễ nhất định giữa thời điểm một sự kiện dữ liệu xảy ra ["thời gian sự kiện", được xác định bởi dấu thời gian trên chính phần tử dữ liệu] và thời gian phần tử dữ liệu thực tế được xử lý ở bất kỳ giai đoạn nào trong . Ngoài ra, không có gì đảm bảo rằng các sự kiện dữ liệu sẽ xuất hiện trong quy trình bán hàng của bạn theo đúng thứ tự mà chúng được tạo

Ví dụ: giả sử chúng ta có một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 đang sử dụng cửa sổ có thời gian cố định, với các cửa sổ dài năm phút. For each window, Beam must collect all the data with an event time timestamp in the given window range [between 0. 00 và 4. 59 trong cửa sổ đầu tiên chẳng hạn]. Dữ liệu có dấu thời gian nằm ngoài phạm vi đó [dữ liệu từ 5. 00 trở lên] thuộc về một cửa sổ khác

Tuy nhiên, dữ liệu không phải lúc nào cũng được đảm bảo đến theo một đường ống theo thứ tự thời gian hoặc luôn đến theo các khoảng thời gian có thể dự đoán được. Beam theo dõi một hình mờ, đó là khái niệm của hệ thống về thời điểm tất cả dữ liệu trong một cửa sổ nhất định có thể được đưa vào đường ống. Sau khi hình mờ đi qua cuối cửa sổ, bất kỳ phần tử nào khác xuất hiện cùng với dấu thời gian trong cửa sổ đó đều được coi là dữ liệu muộn

Từ ví dụ của chúng tôi, giả sử chúng tôi có một hình mờ đơn giản giả định thời gian trễ khoảng 30 giây giữa dấu thời gian dữ liệu [thời gian sự kiện] và thời gian dữ liệu xuất hiện trong đường ống [thời gian xử lý], sau đó Beam sẽ đóng cửa sổ đầu tiên ở mức 5. 30. Nếu một bản ghi dữ liệu đến lúc 5. 34, nhưng với dấu thời gian sẽ đưa nó vào 0. 00-4. 59 cửa sổ [giả sử, 3. 38], thì bản ghi đó là dữ liệu trễ

Ghi chú. Để đơn giản, chúng tôi giả định rằng chúng tôi đang sử dụng một hình mờ rất đơn giản để ước tính thời gian trễ. Trên thực tế, nguồn dữ liệu của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn xác định hình mờ và hình mờ có thể chính xác hoặc phức tạp hơn

Cấu hình cửa sổ mặc định của Beam cố gắng xác định thời điểm tất cả dữ liệu đã đến [dựa trên loại nguồn dữ liệu] và sau đó chuyển hình mờ qua cuối cửa sổ. Cấu hình mặc định này không cho phép dữ liệu trễ. cho phép bạn sửa đổi và tinh chỉnh chiến lược cửa sổ cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Bạn có thể sử dụng trình kích hoạt để quyết định thời điểm mỗi cửa sổ riêng lẻ tổng hợp và báo cáo kết quả của nó, bao gồm cả cách cửa sổ phát ra các phần tử trễ

8. 4. 1. Quản lý dữ liệu muộn

Bạn có thể cho phép dữ liệu trễ bằng cách gọi hoạt động

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
305 khi bạn đặt chiến lược cửa sổ của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73. Ví dụ mã sau minh họa chiến lược tạo cửa sổ sẽ cho phép dữ liệu trễ tối đa hai ngày sau khi kết thúc cửa sổ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
36

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
37

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
38

Khi bạn đặt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
305 trên
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, độ trễ cho phép đó sẽ lan truyền tới bất kỳ
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 nào tiếp theo bắt nguồn từ
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 đầu tiên mà bạn đã áp dụng độ trễ được phép cho. Nếu bạn muốn thay đổi độ trễ được phép sau này trong quy trình bán hàng của mình, bạn phải làm như vậy một cách rõ ràng bằng cách áp dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
311

8. 5. Thêm dấu thời gian vào các phần tử của PCollection

Nguồn không giới hạn cung cấp dấu thời gian cho từng phần tử. Tùy thuộc vào nguồn không giới hạn của bạn, bạn có thể cần định cấu hình cách trích xuất dấu thời gian từ luồng dữ liệu thô

Tuy nhiên, các nguồn có giới hạn [chẳng hạn như tệp từ

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
255] không cung cấp dấu thời gian. Nếu bạn cần dấu thời gian, bạn phải thêm chúng vào các phần tử của
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73

Bạn có thể gán dấu thời gian mới cho các phần tử của

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách áp dụng một biến đổi tạo ra các phần tử mới có dấu thời gian mà bạn đã đặt

Một ví dụ có thể là nếu quy trình của bạn đọc các bản ghi nhật ký từ một tệp đầu vào và mỗi bản ghi nhật ký bao gồm một trường dấu thời gian; . Bạn có thể phân tích cú pháp trường dấu thời gian từ mỗi bản ghi và sử dụng biến đổi

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 với
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 để đính kèm dấu thời gian vào từng thành phần trong
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của bạn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
39

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
40

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
41

9. Gây nên

Ghi chú. The Trigger API in the Beam SDK for Go is currently experimental and subject to change

Khi thu thập và nhóm dữ liệu vào các cửa sổ, Beam sử dụng trình kích hoạt để xác định thời điểm phát ra kết quả tổng hợp của từng cửa sổ [được gọi là ngăn]. Nếu bạn sử dụng cấu hình cửa sổ mặc định của Beam và , Beam sẽ xuất kết quả tổng hợp khi nó và loại bỏ tất cả dữ liệu tiếp theo cho cửa sổ đó

Bạn có thể đặt kích hoạt cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 của mình để thay đổi hành vi mặc định này. Beam cung cấp một số trình kích hoạt dựng sẵn mà bạn có thể đặt

  • Trình kích hoạt thời gian sự kiện. Các trình kích hoạt này hoạt động theo thời gian của sự kiện, như được biểu thị bằng dấu thời gian trên mỗi phần tử dữ liệu. Trình kích hoạt mặc định của Beam dựa trên thời gian của sự kiện
  • Kích hoạt thời gian xử lý. Các trình kích hoạt này hoạt động theo thời gian xử lý – thời điểm phần tử dữ liệu được xử lý ở bất kỳ giai đoạn cụ thể nào trong quy trình
  • Trình kích hoạt theo hướng dữ liệu. Các trình kích hoạt này hoạt động bằng cách kiểm tra dữ liệu khi dữ liệu đến trong mỗi cửa sổ và kích hoạt khi dữ liệu đó đáp ứng một thuộc tính nhất định. Hiện tại, trình kích hoạt theo hướng dữ liệu chỉ hỗ trợ kích hoạt sau một số phần tử dữ liệu nhất định
  • kích hoạt tổng hợp. Các trình kích hoạt này kết hợp nhiều trình kích hoạt theo nhiều cách khác nhau

Ở cấp độ cao, trình kích hoạt cung cấp hai khả năng bổ sung so với việc chỉ xuất ra ở cuối cửa sổ

  • Trình kích hoạt cho phép Beam phát ra kết quả sớm, trước khi tất cả dữ liệu trong một cửa sổ nhất định đến. Ví dụ: phát ra sau một khoảng thời gian nhất định hoặc sau khi một số phần tử nhất định đến
  • Triggers allow processing of late data by triggering after the event time watermark passes the end of the window

Những khả năng này cho phép bạn kiểm soát luồng dữ liệu của mình và cân bằng giữa các yếu tố khác nhau tùy thuộc vào trường hợp sử dụng của bạn

  • sự hoàn thiện. Việc có tất cả dữ liệu trước khi tính toán kết quả quan trọng như thế nào?
  • độ trễ. Bạn muốn chờ dữ liệu trong bao lâu?
  • Cost. Bạn sẵn sàng chi bao nhiêu tiền/sức mạnh tính toán để giảm độ trễ?

Ví dụ: một hệ thống yêu cầu các bản cập nhật nhạy cảm với thời gian có thể sử dụng trình kích hoạt dựa trên thời gian nghiêm ngặt phát ra một cửa sổ sau mỗi N giây, đánh giá tính kịp thời hơn tính đầy đủ của dữ liệu. Một hệ thống coi trọng tính đầy đủ của dữ liệu hơn thời gian chính xác của kết quả có thể chọn sử dụng trình kích hoạt mặc định của Beam, kích hoạt ở cuối cửa sổ

Bạn cũng có thể đặt trình kích hoạt cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 không giới hạn sử dụng. Điều này có thể hữu ích khi bạn muốn quy trình của mình cung cấp các bản cập nhật định kỳ trên tập dữ liệu không giới hạn — ví dụ: mức trung bình đang chạy của tất cả dữ liệu được cung cấp cho thời điểm hiện tại, được cập nhật N giây hoặc mỗi N phần tử

9. 1. Trình kích hoạt thời gian sự kiện

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
320 hoạt động vào thời gian diễn ra sự kiện. Trình kích hoạt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
320 phát ra nội dung của cửa sổ sau khi vượt qua phần cuối của cửa sổ, dựa trên dấu thời gian được đính kèm với các phần tử dữ liệu. Hình mờ là thước đo tiến độ toàn cầu và là khái niệm của Beam về tính đầy đủ của đầu vào trong quy trình của bạn tại bất kỳ điểm nào. ______54_______322 ______54_______320
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
324
chỉ kích hoạt khi hình mờ đi qua cuối cửa sổ.

Ngoài ra, bạn có thể định cấu hình trình kích hoạt kích hoạt nếu quy trình của bạn nhận dữ liệu trước hoặc sau khi kết thúc cửa sổ

Ví dụ sau đây cho thấy một kịch bản thanh toán và sử dụng cả kích hoạt sớm và muộn

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
42

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
43

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
44

9. 1. 1. Trình kích hoạt mặc định

Trình kích hoạt mặc định cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 dựa trên thời gian sự kiện và phát ra kết quả của cửa sổ khi hình mờ của Beam đi qua cuối cửa sổ, sau đó kích hoạt mỗi khi dữ liệu trễ đến

Tuy nhiên, nếu bạn đang sử dụng cả cấu hình cửa sổ mặc định và trình kích hoạt mặc định, trình kích hoạt mặc định sẽ phát chính xác một lần và dữ liệu muộn sẽ bị loại bỏ. Điều này là do cấu hình cửa sổ mặc định có giá trị độ trễ cho phép là 0. Xem phần Xử lý dữ liệu muộn để biết thông tin về cách sửa đổi hành vi này

9. 2. Kích hoạt thời gian xử lý

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
326 hoạt động theo thời gian xử lý. Ví dụ: trình kích hoạt ______54_______327 ______54_______326
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
329
phát ra một cửa sổ sau một khoảng thời gian nhất định . Thời gian xử lý được xác định bởi đồng hồ hệ thống, thay vì dấu thời gian của phần tử dữ liệu.

Trình kích hoạt

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
326 hữu ích để kích hoạt kết quả sớm từ một cửa sổ, đặc biệt là cửa sổ có khung thời gian lớn, chẳng hạn như một cửa sổ toàn cầu

9. 3. Data-driven triggers

Beam cung cấp một trình kích hoạt theo hướng dữ liệu,

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
331
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
332
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
333
. This trigger works on an element count; it fires after the current pane has collected at least N elements. This allows a window to emit early results [before all the data has accumulated], which can be particularly useful if you are using a single global window.

Ví dụ: điều quan trọng cần lưu ý là nếu bạn chỉ định ______54_______334 CounterCount[50] . Nếu 32 yếu tố quan trọng với bạn, hãy cân nhắc sử dụng để kết hợp nhiều điều kiện. Điều này cho phép bạn chỉ định nhiều điều kiện bắn, chẳng hạn như “bắn khi tôi nhận được 50 phần tử hoặc cứ sau 1 giây”. and only 32 elements arrive, those 32 elements sit around forever. If the 32 elements are important to you, consider using to combine multiple conditions. This allows you to specify multiple firing conditions such as “fire either when I receive 50 elements, or every 1 second”.

9. 4. Đặt trình kích hoạt

Khi bạn đặt chức năng tạo cửa sổ cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách sử dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
241
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
338
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
339
transform, you can also specify a trigger.

Bạn đặt [các] trình kích hoạt cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách gọi phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
341 trên kết quả biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
342 của bạn. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. Dòng cuối cùng trong mẫu mã,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
344, đặt chế độ tích lũy của cửa sổ

Bạn đặt [các] trình kích hoạt cho

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách đặt tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
346 khi bạn sử dụng biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
338. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. Tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
349 đặt chế độ tích lũy của cửa sổ

Bạn đặt [các] trình kích hoạt cho một

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 bằng cách chuyển tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
351 khi bạn sử dụng biến đổi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
339. Mẫu mã này đặt trình kích hoạt dựa trên thời gian cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, trình kích hoạt này đưa ra kết quả một phút sau khi phần tử đầu tiên trong cửa sổ đó được xử lý. Tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
354 đặt chế độ tích lũy của cửa sổ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
45

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
46

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
47

9. 4. 1. Chế độ tích lũy cửa sổ

Khi bạn chỉ định trình kích hoạt, bạn cũng phải đặt chế độ tích lũy của cửa sổ. Khi trình kích hoạt kích hoạt, nó sẽ phát ra nội dung hiện tại của cửa sổ dưới dạng một ngăn. Vì trình kích hoạt có thể kích hoạt nhiều lần, nên chế độ tích lũy sẽ xác định xem hệ thống sẽ tích lũy các ô cửa sổ khi trình kích hoạt kích hoạt hay loại bỏ chúng

Để đặt một cửa sổ tích lũy các ô được tạo khi trình kích hoạt kích hoạt, hãy gọi_______54_______355 khi bạn đặt kích hoạt. Để đặt một cửa sổ loại bỏ các ô đã kích hoạt, hãy gọi ____54_______344

Để đặt một cửa sổ tích lũy các ô được tạo khi kích hoạt kích hoạt, hãy đặt tham số

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
349 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
358 khi bạn đặt kích hoạt. Để đặt một cửa sổ loại bỏ các ô đã nung, hãy đặt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
349 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
360

Để đặt một cửa sổ tích lũy các ô được tạo khi trình kích hoạt kích hoạt, hãy đặt tham số

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
354 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
362 khi bạn đặt kích hoạt. Để đặt một cửa sổ loại bỏ các tấm đã nung, hãy đặt
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
354 thành
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
364

Hãy xem một ví dụ sử dụng

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 với cửa sổ thời gian cố định và trình kích hoạt dựa trên dữ liệu. Đây là điều bạn có thể làm nếu, ví dụ: mỗi cửa sổ biểu thị giá trị trung bình đang chạy trong mười phút, nhưng bạn muốn hiển thị giá trị hiện tại của giá trị trung bình trong giao diện người dùng thường xuyên hơn mười phút một lần. Chúng tôi sẽ giả định các điều kiện sau

  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 sử dụng cửa sổ thời gian cố định 10 phút
  • await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    73 có trình kích hoạt lặp lại sẽ kích hoạt mỗi khi 3 phần tử đến

Sơ đồ sau hiển thị các sự kiện dữ liệu cho khóa X khi chúng đến PCollection và được gán cho các cửa sổ. Để sơ đồ đơn giản hơn một chút, chúng ta sẽ giả sử rằng tất cả các sự kiện đều đến trong quy trình theo thứ tự

9. 4. 1. 1. chế độ tích lũy

If our trigger is set to accumulating mode, the trigger emits the following values each time it fires. Hãy nhớ rằng trình kích hoạt sẽ kích hoạt mỗi khi ba yếu tố đến

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
489. 4. 1. 2. chế độ loại bỏ

Nếu trình kích hoạt của chúng tôi được đặt ở chế độ loại bỏ, trình kích hoạt sẽ phát ra các giá trị sau trên mỗi lần kích hoạt

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
49

9. 4. 2. Xử lý dữ liệu muộn

Nếu bạn muốn quy trình của mình xử lý dữ liệu đến sau khi hình mờ đi qua cuối cửa sổ, bạn có thể áp dụng độ trễ cho phép khi đặt cấu hình cửa sổ của mình. Điều này giúp trình kích hoạt của bạn có cơ hội phản ứng với dữ liệu muộn. Nếu độ trễ cho phép được đặt, trình kích hoạt mặc định sẽ đưa ra kết quả mới ngay lập tức bất cứ khi nào có dữ liệu trễ

Bạn đặt độ trễ cho phép bằng cách sử dụng ______54_______368

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
369 ______54_______370 when you set your windowing function:

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
50

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
51

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
52

Độ trễ cho phép này lan truyền tới tất cả các

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 được tạo ra do áp dụng các phép biến đổi cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 ban đầu. Nếu bạn muốn thay đổi độ trễ được phép sau này trong quy trình bán hàng của mình, bạn có thể đăng ký
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
311
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
369
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
370
again, explicitly.

9. 5. kích hoạt tổng hợp

Bạn có thể kết hợp nhiều trình kích hoạt để tạo thành trình kích hoạt tổng hợp và có thể chỉ định trình kích hoạt để phát ra kết quả nhiều lần, nhiều nhất một lần hoặc trong các điều kiện tùy chỉnh khác

9. 5. 1. Các loại kích hoạt tổng hợp

Beam includes the following composite triggers

  • Bạn có thể thêm các lần kích hoạt sớm hoặc kích hoạt muộn bổ sung cho
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    376 thông qua
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    377 và
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    378
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    379 chỉ định trình kích hoạt thực thi mãi mãi. Bất cứ khi nào các điều kiện của trình kích hoạt được đáp ứng, nó sẽ khiến một cửa sổ phát ra kết quả rồi đặt lại và bắt đầu lại. Có thể hữu ích khi kết hợp
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    379 với
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    381 để chỉ định một điều kiện khiến trình kích hoạt lặp lại dừng lại
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    382 kết hợp nhiều kích hoạt để kích hoạt theo một trình tự cụ thể. Mỗi lần một trình kích hoạt trong chuỗi phát ra một cửa sổ, trình tự sẽ chuyển sang trình kích hoạt tiếp theo
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    383 nhận nhiều trình kích hoạt và phát ra lần đầu tiên bất kỳ trình kích hoạt đối số nào của nó được thỏa mãn. Điều này tương đương với phép toán OR logic cho nhiều trình kích hoạt
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    384 nhận nhiều trình kích hoạt và phát ra khi tất cả các trình kích hoạt đối số của nó được thỏa mãn. Điều này tương đương với phép toán AND logic cho nhiều trình kích hoạt
  • import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    385 có thể đóng vai trò là điều kiện cuối cùng để khiến bất kỳ bộ kích hoạt nào kích hoạt lần cuối và không bao giờ kích hoạt nữa

9. 5. 2. Bố cục với AfterWatermark

Một số trình kích hoạt tổng hợp hữu ích nhất kích hoạt một lần duy nhất khi Beam ước tính rằng tất cả dữ liệu đã đến [i. e. khi hình mờ đi qua cuối cửa sổ] kết hợp với một trong hai hoặc cả hai điều sau

  • Các lần kích hoạt đầu cơ trước khi hình mờ đi qua cuối cửa sổ để cho phép xử lý một phần kết quả nhanh hơn

  • Các lần kích hoạt muộn xảy ra sau khi hình mờ đi qua cuối cửa sổ, để cho phép xử lý dữ liệu đến muộn

Bạn có thể diễn đạt mẫu này bằng cách sử dụng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
320. Ví dụ: mã kích hoạt ví dụ sau kích hoạt trong các điều kiện sau

  • Theo ước tính của Beam, tất cả dữ liệu đã đến [hình mờ vượt qua cuối cửa sổ]

  • Any time late data arrives, after a ten-minute delay

  • Sau hai ngày, chúng tôi cho rằng sẽ không có thêm dữ liệu quan tâm nào đến và trình kích hoạt sẽ ngừng thực thi

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
53

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
54

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
55

9. 5. 3. Các kích hoạt tổng hợp khác

Bạn cũng có thể xây dựng các loại trình kích hoạt tổng hợp khác. Mã ví dụ sau hiển thị trình kích hoạt tổng hợp đơn giản kích hoạt bất cứ khi nào ngăn có ít nhất 100 phần tử hoặc sau một phút

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
56

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
57

10. số liệu

Trong mô hình Beam, các chỉ số cung cấp một số thông tin chi tiết về trạng thái hiện tại của quy trình người dùng, có thể xảy ra trong khi quy trình đang chạy. Có thể có những lý do khác nhau cho điều đó, ví dụ

  • Kiểm tra số lỗi gặp phải khi chạy một bước cụ thể trong quy trình;
  • Theo dõi số lượng RPC được thực hiện cho dịch vụ phụ trợ;
  • Truy xuất số lượng chính xác số lượng phần tử đã được xử lý;
  • …và như thế

10. 1. Các khái niệm chính về chỉ số Beam

  • được đặt tên. Mỗi chỉ số có một tên bao gồm một không gian tên và một tên thực tế. Không gian tên có thể được sử dụng để phân biệt giữa nhiều chỉ số có cùng tên và cũng cho phép truy vấn tất cả các chỉ số trong một không gian tên cụ thể
  • phạm vi. Mỗi số liệu được báo cáo theo một bước cụ thể trong quy trình bán hàng, cho biết mã nào đang chạy khi số liệu đó tăng lên
  • Được tạo động. Các chỉ số có thể được tạo trong thời gian chạy mà không cần khai báo trước chúng, giống như cách tạo một trình ghi nhật ký. Điều này giúp tạo ra các số liệu trong mã tiện ích dễ dàng hơn và báo cáo chúng một cách hữu ích
  • xuống cấp một cách duyên dáng. Nếu một người chạy không hỗ trợ một số phần của báo cáo chỉ số, thì hành vi dự phòng là bỏ cập nhật chỉ số thay vì làm hỏng quy trình. Nếu một trình chạy không hỗ trợ một số phần của số liệu truy vấn, thì trình chạy sẽ không trả về dữ liệu được liên kết

Các chỉ số được báo cáo hoàn toàn nằm trong phạm vi biến đổi trong quy trình đã báo cáo các chỉ số đó. Điều này cho phép báo cáo cùng một tên chỉ số ở nhiều nơi và xác định giá trị mà mỗi biến đổi được báo cáo, cũng như tổng hợp chỉ số trên toàn bộ quy trình

Ghi chú. Việc các số liệu có thể truy cập được trong quá trình thực thi đường ống hay chỉ sau khi các công việc đã hoàn thành là phụ thuộc vào người chạy.

10. 2. Các loại chỉ số

Có ba loại số liệu được hỗ trợ tại thời điểm này.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
387,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
388 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
389

Trong Beam SDK for Go, một

public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
10 do khung cung cấp phải được chuyển đến chỉ số, nếu không giá trị chỉ số sẽ không được ghi lại. Khung sẽ tự động cung cấp một ____73_______10 hợp lệ cho ____65_______36 và các phương thức tương tự khi đó là tham số đầu tiên

Phản đối. Số liệu báo cáo một giá trị dài duy nhất và có thể tăng hoặc giảm

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
58

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
59

Phân bổ. Một số liệu báo cáo thông tin về việc phân phối các giá trị được báo cáo

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
60

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
61

máy đo. Số liệu báo cáo giá trị mới nhất trong số các giá trị được báo cáo. Vì các số liệu được thu thập từ nhiều công nhân nên giá trị có thể không phải là giá trị cuối cùng tuyệt đối mà là một trong những giá trị mới nhất

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
62

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
63

10. 3. Số liệu truy vấn

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
393 có một phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
394 trả về một đối tượng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
395 cho phép truy cập các chỉ số. Phương pháp chính có sẵn trong
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
395 cho phép truy vấn tất cả các chỉ số phù hợp với một bộ lọc nhất định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
397 có phương thức
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
398 trả về đối tượng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
399 cho phép truy cập số liệu. Phương pháp chính có sẵn trong
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
399 cho phép truy vấn tất cả các chỉ số phù hợp với một bộ lọc nhất định. Nó nhận một vị ngữ có loại tham số
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
401, có thể được sử dụng cho các bộ lọc tùy chỉnh

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
64

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
65

10. 4. Sử dụng số liệu trong quy trình

Bên dưới, có một ví dụ đơn giản về cách sử dụng chỉ số

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
387 trong quy trình người dùng

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
66

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
67

10. 5. Xuất chỉ số

Số liệu chùm tia có thể được xuất sang các phần chìm bên ngoài. Nếu một số liệu chìm được thiết lập trong cấu hình, người chạy sẽ đẩy các số liệu tới nó trong khoảng thời gian 5 giây mặc định. Cấu hình được giữ trong lớp MetricsOptions. Nó chứa cấu hình thời gian đẩy và cũng có các tùy chọn cụ thể chìm như loại và URL. Hiện tại, chỉ có REST HTTP và các phần chìm Graphite được hỗ trợ và chỉ các trình chạy Flink và Spark hỗ trợ xuất số liệu

Ngoài ra, các số liệu Beam được xuất sang bảng điều khiển Spark và Flink bên trong để được tư vấn trong giao diện người dùng tương ứng của chúng

11. Trạng thái và bộ hẹn giờ

Các cơ sở kích hoạt và cửa sổ của Beam cung cấp khả năng trừu tượng hóa mạnh mẽ để nhóm và tổng hợp dữ liệu đầu vào không giới hạn dựa trên dấu thời gian. Tuy nhiên, có những trường hợp sử dụng tổng hợp mà các nhà phát triển có thể yêu cầu mức độ kiểm soát cao hơn mức độ kiểm soát được cung cấp bởi các cửa sổ và trình kích hoạt. Beam cung cấp API để quản lý trạng thái theo từng khóa theo cách thủ công, cho phép kiểm soát chi tiết các tập hợp

Trạng thái mô hình API trạng thái của Beam trên mỗi khóa. To use the state API, you start out with a keyed

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73, which in Java is modeled as a
const pipeline_options = {
  runner: "default",
  project: "my_project",
};

const runner = beam.createRunner[pipeline_options];

const runnerFromCommandLineOptions = beam.createRunner[yargs.argv];
10. A
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 processing this
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 can now declare state variables. Bên trong
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56, các biến trạng thái này có thể được sử dụng để viết hoặc cập nhật trạng thái cho khóa hiện tại hoặc để đọc trạng thái trước đó được viết cho khóa đó. Trạng thái luôn chỉ nằm trong phạm vi đầy đủ đối với khóa xử lý hiện tại

Cửa sổ vẫn có thể được sử dụng cùng với xử lý trạng thái. Tất cả trạng thái cho một khóa nằm trong phạm vi cửa sổ hiện tại. Điều này có nghĩa là lần đầu tiên một khóa được nhìn thấy cho một cửa sổ nhất định, bất kỳ trạng thái nào được đọc sẽ trả về trạng thái trống và trình chạy có thể thu gom rác trạng thái khi một cửa sổ hoàn thành. Nó cũng thường hữu ích khi sử dụng các tập hợp cửa sổ của Beam trước toán tử trạng thái. Ví dụ: sử dụng bộ kết hợp để tổng hợp trước dữ liệu, sau đó lưu trữ dữ liệu đã tổng hợp bên trong trạng thái. Các cửa sổ hợp nhất hiện không được hỗ trợ khi sử dụng trạng thái và bộ hẹn giờ

Đôi khi xử lý trạng thái được sử dụng để triển khai xử lý kiểu máy trạng thái bên trong một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. Khi thực hiện việc này, cần phải lưu ý rằng các thành phần trong PCCollection đầu vào không có thứ tự được đảm bảo và để đảm bảo rằng logic chương trình có khả năng phục hồi với điều này. Các bài kiểm tra đơn vị được viết bằng DirectRunner sẽ xáo trộn thứ tự xử lý phần tử và được khuyến nghị để kiểm tra tính chính xác

Trong Java, DoFn tuyên bố các trạng thái sẽ được truy cập bằng cách tạo các biến thành viên

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
409 cuối cùng đại diện cho mỗi trạng thái. Mỗi tiểu bang phải được đặt tên bằng cách sử dụng chú thích
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
410; . Một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể khai báo nhiều biến trạng thái

Trong Python, DoFn khai báo các trạng thái được truy cập bằng cách tạo các biến thành viên lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
409 đại diện cho từng trạng thái. Mỗi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
409 được khởi tạo với một tên, tên này là duy nhất cho một ParDo trong biểu đồ và không liên quan đến các nút khác trong biểu đồ. A
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 can declare multiple state variables

Trong Go, DoFn khai báo các trạng thái sẽ được truy cập bằng cách tạo các biến thành viên cấu trúc trạng thái đại diện cho từng trạng thái. Mỗi biến trạng thái được khởi tạo bằng một khóa, khóa này là duy nhất cho một ParDo trong biểu đồ và không liên quan đến các nút khác trong biểu đồ. Nếu không cung cấp tên, khóa sẽ mặc định là tên của biến thành viên. Một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể khai báo nhiều biến trạng thái

Ghi chú. Beam SDK cho Bản mô tả chưa hỗ trợ API Trạng thái và Hẹn giờ, nhưng có thể sử dụng các tính năng này từ các đường dẫn ngôn ngữ chéo [xem bên dưới]

11. 1. Các loại trạng thái

Beam cung cấp một số loại trạng thái

ValueState

ValueState là một giá trị trạng thái vô hướng. Đối với mỗi khóa trong đầu vào, một ValueState sẽ lưu trữ một giá trị đã nhập có thể được đọc và sửa đổi bên trong các phương thức

PipelineOptions options =
    PipelineOptionsFactory.fromArgs[args].withValidation[].create[];
12 hoặc
public interface MyOptions extends PipelineOptions {
    String getInput[];
    void setInput[String input];

    String getOutput[];
    void setOutput[String output];
}
41 của DoFn. Nếu loại ValueState có bộ mã hóa được đăng ký, thì Beam sẽ tự động suy ra bộ mã hóa cho giá trị trạng thái. Mặt khác, một bộ mã hóa có thể được chỉ định rõ ràng khi tạo ValueState. Ví dụ: ParDo sau đây tạo một biến trạng thái duy nhất tích lũy số lượng phần tử được nhìn thấy

Ghi chú.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
418 được gọi là
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
419 trong Python SDK

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
68

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
69

Beam cũng cho phép chỉ định rõ ràng một bộ mã hóa cho các giá trị

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
418. For example

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
70

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
71

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
72

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
73

Kết hợpTrạng thái

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
421 cho phép bạn tạo một đối tượng trạng thái được cập nhật bằng bộ kết hợp Beam. Ví dụ: ví dụ về
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
418 trước đó có thể được viết lại để sử dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
421

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
74

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
75

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
76

TúiBang

Một trường hợp sử dụng phổ biến cho trạng thái là tích lũy nhiều phần tử.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
424 cho phép tích lũy một tập hợp các phần tử không có thứ tự. Điều này cho phép thêm các phần tử vào bộ sưu tập mà không yêu cầu đọc toàn bộ bộ sưu tập trước, đây là một hiệu quả đạt được. Ngoài ra, các vận động viên hỗ trợ đọc theo trang có thể cho phép các túi riêng lẻ lớn hơn bộ nhớ khả dụng

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
77

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
78

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
35

11. 2. Đọc trạng thái hoãn lại

Khi một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 chứa nhiều thông số trạng thái, việc đọc từng thông số theo thứ tự có thể chậm. Gọi hàm
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
426 ở trạng thái có thể khiến người chạy thực hiện thao tác chặn đọc. Thực hiện nhiều lần đọc chặn theo trình tự sẽ thêm độ trễ cho quá trình xử lý phần tử. Nếu bạn biết rằng một trạng thái sẽ luôn được đọc, bạn có thể chú thích trạng thái đó là @AlwaysFetched, sau đó trình chạy có thể tìm nạp trước tất cả các trạng thái cần thiết. Ví dụ

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
80

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
81

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
82

Tuy nhiên, nếu có các đường dẫn mã trong đó các trạng thái không được tìm nạp, thì việc chú thích bằng @AlwaysFetched sẽ thêm tính năng tìm nạp không cần thiết cho các đường dẫn đó. Trong trường hợp này, phương thức readLater cho phép người chạy biết rằng trạng thái sẽ được đọc trong tương lai, cho phép nhiều lần đọc trạng thái được gộp lại với nhau

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
83

11. 3. hẹn giờ

Beam cung cấp API gọi lại hẹn giờ cho mỗi phím. Điều này cho phép xử lý chậm dữ liệu được lưu trữ bằng API trạng thái. Bộ hẹn giờ có thể được đặt thành gọi lại tại thời điểm sự kiện hoặc dấu thời gian xử lý. Mỗi bộ đếm thời gian được xác định bằng TimerId. Chỉ có thể đặt bộ hẹn giờ nhất định cho một phím cho một dấu thời gian. Cuộc gọi được đặt trên bộ hẹn giờ sẽ ghi đè thời gian kích hoạt trước đó cho bộ hẹn giờ của phím đó

11. 3. 1. bộ hẹn giờ sự kiện

Bộ hẹn giờ thời gian sự kiện kích hoạt khi hình mờ đầu vào cho DoFn vượt qua thời gian mà bộ hẹn giờ được đặt, nghĩa là người chạy tin rằng không có thêm yếu tố nào được xử lý bằng dấu thời gian trước dấu thời gian của bộ hẹn giờ. Điều này cho phép tổng hợp thời gian sự kiện

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
84

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
85

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 2. bộ định thời gian xử lý

Bộ hẹn giờ thời gian xử lý kích hoạt khi thời gian thực của đồng hồ treo tường trôi qua. Điều này thường được sử dụng để tạo các lô dữ liệu lớn hơn trước khi xử lý. Nó cũng có thể được sử dụng để lên lịch các sự kiện sẽ xảy ra vào một thời điểm cụ thể. Just like with event-time timers, processing-time timers are per key - each key has a separate copy of the timer

Mặc dù bộ hẹn giờ thời gian xử lý có thể được đặt thành dấu thời gian tuyệt đối, nhưng rất phổ biến để đặt chúng thành phần bù so với thời gian hiện tại. Trong Java, các phương thức

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
427 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
428 có thể được sử dụng để thực hiện điều này

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
87

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
88

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 3. Thẻ hẹn giờ động

Beam cũng hỗ trợ tự động thiết lập thẻ hẹn giờ bằng cách sử dụng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
429 trong SDK Java. Điều này cho phép đặt nhiều bộ hẹn giờ khác nhau trong một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 và cho phép các thẻ bộ hẹn giờ được chọn động - e. g. dựa trên dữ liệu trong các yếu tố đầu vào. Chỉ có thể đặt bộ hẹn giờ với một thẻ cụ thể thành một dấu thời gian duy nhất, do đó, việc đặt lại bộ hẹn giờ có tác dụng ghi đè thời gian hết hạn trước đó cho bộ hẹn giờ với thẻ đó. Mỗi
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
429 được xác định bằng id họ bộ hẹn giờ và các bộ hẹn giờ trong các họ bộ hẹn giờ khác nhau là độc lập

Trong SDK Python, thẻ hẹn giờ động có thể được chỉ định trong khi gọi

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
432 hoặc
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
433. Theo mặc định, thẻ hẹn giờ là một chuỗi rỗng nếu không được chỉ định

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
90

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
91

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 3. 4. Dấu thời gian đầu ra của bộ hẹn giờ

Theo mặc định, bộ hẹn giờ theo thời gian sự kiện sẽ giữ hình mờ đầu ra của

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 cho dấu thời gian của bộ hẹn giờ. Điều này có nghĩa là nếu bộ hẹn giờ được đặt thành 12 giờ đêm, thì bất kỳ tập hợp cửa sổ hoặc bộ hẹn giờ sự kiện nào sau này trong biểu đồ quy trình kết thúc sau 12 giờ đêm sẽ không hết hạn. Dấu thời gian của bộ hẹn giờ cũng là dấu thời gian đầu ra mặc định cho lệnh gọi lại bộ hẹn giờ. This means that any elements output from the onTimer method will have a timestamp equal to the timestamp of the timer firing. Đối với bộ hẹn giờ thời gian xử lý, dấu thời gian đầu ra mặc định và giữ hình mờ là giá trị của hình mờ đầu vào tại thời điểm bộ hẹn giờ được đặt

Trong một số trường hợp, DoFn cần xuất dấu thời gian sớm hơn thời gian hết hạn của bộ hẹn giờ và do đó cũng cần giữ hình mờ đầu ra của nó đối với các dấu thời gian đó. Ví dụ: hãy xem xét quy trình sau tạm thời nhóm các bản ghi vào trạng thái và đặt bộ hẹn giờ để thoát trạng thái. Mã này có thể xuất hiện đúng, nhưng sẽ không hoạt động bình thường

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
93

Vấn đề với mã này là ParDo đang đệm các phần tử, tuy nhiên không có gì ngăn hình mờ vượt qua dấu thời gian của các phần tử đó, vì vậy tất cả các phần tử đó có thể bị loại bỏ dưới dạng dữ liệu muộn. Để ngăn điều này xảy ra, dấu thời gian đầu ra cần được đặt trên bộ hẹn giờ để ngăn hình mờ vượt qua dấu thời gian của phần tử tối thiểu. Đoạn mã sau chứng minh điều này

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
94

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
95

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 4. Tình trạng thu gom rác

Trạng thái trên mỗi khóa cần được thu gom rác hoặc cuối cùng kích thước ngày càng tăng của trạng thái có thể tác động tiêu cực đến hiệu suất. Có hai chiến lược phổ biến cho trạng thái thu gom rác

11. 4. 1. Sử dụng cửa sổ để thu gom rác

Tất cả trạng thái và bộ hẹn giờ cho một khóa nằm trong phạm vi cửa sổ chứa khóa đó. Điều này có nghĩa là tùy thuộc vào dấu thời gian của phần tử đầu vào, ParDo sẽ thấy các giá trị khác nhau cho trạng thái tùy thuộc vào cửa sổ mà phần tử đó rơi vào. Ngoài ra, khi hình mờ đầu vào đi qua cuối cửa sổ, trình chạy sẽ thu thập tất cả trạng thái cho cửa sổ đó. [note. if allowed lateness is set to a positive value for the window, the runner must wait for the watermark to pass the end of the window plus the allowed lateness before garbage collecting state]. Điều này có thể được sử dụng như một chiến lược thu gom rác

Ví dụ, được đưa ra sau đây

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
97

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
98

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
99

Trạng thái cửa hàng

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
56 này mỗi ngày. Khi đường ống xử lý xong dữ liệu cho một ngày nhất định, tất cả trạng thái của ngày đó sẽ được thu gom rác

11. 4. 1. Sử dụng bộ hẹn giờ để thu gom rác

Trong một số trường hợp, rất khó để tìm ra chiến lược cửa sổ mô hình hóa chiến lược thu gom rác mong muốn. Ví dụ: mong muốn chung là chuyển trạng thái thu gom rác cho một khóa sau khi không thấy hoạt động nào trên khóa trong một thời gian. Điều này có thể được thực hiện bằng cách cập nhật bộ đếm thời gian mà trạng thái thu gom rác. Ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
00

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
01

// beam.Init[] is an initialization hook that must be called
// near the beginning of main[], before creating a pipeline.
beam.Init[]

// Create the Pipeline object and root scope.
pipeline, scope := beam.NewPipelineWithRoot[]
86

11. 5. Ví dụ về trạng thái và bộ hẹn giờ

Sau đây là một số ví dụ sử dụng trạng thái và bộ hẹn giờ

11. 5. 1. Kết hợp các nhấp chuột và lượt xem

Trong ví dụ này, quy trình đang xử lý dữ liệu từ trang chủ của trang thương mại điện tử. There are two input streams. luồng lượt xem, biểu thị các liên kết sản phẩm được đề xuất hiển thị cho người dùng trên trang chủ và luồng lượt nhấp, biểu thị lượt nhấp thực tế của người dùng vào các liên kết này. Mục tiêu của quy trình là kết hợp các sự kiện nhấp chuột với các sự kiện xem, xuất ra một sự kiện đã tham gia mới chứa thông tin từ cả hai sự kiện. Mỗi liên kết có một mã định danh duy nhất có trong cả sự kiện xem và sự kiện tham gia

Nhiều sự kiện xem sẽ không bao giờ được theo dõi bằng các nhấp chuột. Đường ống này sẽ đợi một giờ cho một nhấp chuột, sau đó nó sẽ từ bỏ tham gia này. Mặc dù mỗi sự kiện nhấp chuột phải có một sự kiện xem, nhưng một số ít sự kiện xem có thể bị mất và không bao giờ được đưa vào quy trình Beam; . Các sự kiện đầu vào không được sắp xếp - có thể thấy sự kiện nhấp chuột trước sự kiện xem. Thời gian chờ tham gia một giờ phải dựa trên thời gian sự kiện, không phải thời gian xử lý

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
03

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
04

11. 5. 2. RPC theo đợt

Trong ví dụ này, các yếu tố đầu vào đang được chuyển tiếp đến một dịch vụ RPC bên ngoài. RPC chấp nhận các yêu cầu hàng loạt - nhiều sự kiện cho cùng một người dùng có thể được xử lý theo đợt trong một lệnh gọi RPC. Vì dịch vụ RPC này cũng áp đặt giới hạn tốc độ nên chúng tôi muốn gộp các sự kiện có giá trị 10 giây lại với nhau để giảm số lượng cuộc gọi

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
05

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
06

12. Có thể chia tách
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
67

Một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 có thể chia được [SDF] cho phép người dùng tạo các thành phần mô-đun có chứa I/O [và một số ] nâng cao. Having modular I/O components that can be connected to each other simplify typical patterns that users want. Ví dụ: trường hợp sử dụng phổ biến là đọc tên tệp từ hàng đợi tin nhắn, sau đó phân tích cú pháp các tệp đó. Theo truyền thống, người dùng được yêu cầu viết một trình kết nối I/O duy nhất chứa logic cho hàng đợi tin nhắn và trình đọc tệp [độ phức tạp tăng lên] hoặc chọn sử dụng lại I/O hàng đợi tin nhắn theo sau bởi một
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 thông thường đọc tệp [ . Với SDF, chúng tôi mang đến sự phong phú của các API I/O của Apache Beam thành một mô-đun cho phép
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 trong khi vẫn duy trì hiệu suất của các đầu nối I/O truyền thống

12. 1. Khái niệm cơ bản về SDF

Ở cấp độ cao, SDF chịu trách nhiệm xử lý các cặp phần tử và giới hạn. Một hạn chế đại diện cho một tập hợp con công việc cần thiết phải được thực hiện khi xử lý phần tử

Thực hiện một SDF theo các bước sau

  1. Mỗi phần tử được ghép nối với một hạn chế [e. g. tên tệp được ghép nối với phạm vi bù đại diện cho toàn bộ tệp]
  2. Mỗi cặp phần tử và giới hạn được tách ra [e. g. phạm vi bù được chia thành các phần nhỏ hơn]
  3. Người chạy phân phối lại các cặp phần tử và hạn chế cho một số công nhân
  4. Các cặp phần tử và giới hạn được xử lý song song [e. g. tập tin được đọc]. Trong bước cuối cùng này, cặp phần tử và giới hạn có thể tạm dừng quá trình xử lý của chính nó và/hoặc được chia thành các cặp phần tử và giới hạn khác

12. 1. 1. Một SDF cơ bản

A basic SDF is composed of three parts. hạn chế, nhà cung cấp hạn chế và trình theo dõi hạn chế. Nếu bạn muốn kiểm soát hình mờ, đặc biệt là trong đường ống phát trực tuyến, cần có thêm hai thành phần. nhà cung cấp công cụ ước tính thủy vân và công cụ ước tính thủy vân

Hạn chế là một đối tượng do người dùng định nghĩa được sử dụng để biểu thị một tập hợp con công việc cho một phần tử nhất định. Ví dụ: chúng tôi đã xác định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
440 là hạn chế để biểu thị các vị trí bù trong Java và

Nhà cung cấp hạn chế cho phép các tác giả SDF ghi đè các triển khai mặc định, bao gồm cả các triển khai để phân tách và định cỡ. Trong Java và , đây là

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. có một loại
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
442 chuyên dụng

Trình theo dõi hạn chế chịu trách nhiệm theo dõi tập hợp con nào của hạn chế đã được hoàn thành trong quá trình xử lý. Để biết chi tiết về API, hãy đọc tài liệu tham khảo và Java

Có một số triển khai

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
443 tích hợp được định nghĩa trong Java

  1. Bù đắpPhạm viTracker
  2. GrowableOffsetRangeTracker
  3. ByteKeyRangeTracker

SDF cũng có triển khai

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
443 tích hợp sẵn trong Python

Go cũng có loại

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
443 tích hợp sẵn

  1. Bù đắpPhạm viTracker

Trạng thái hình mờ là một đối tượng do người dùng xác định được sử dụng để tạo một

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 từ một
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
447. Trạng thái hình mờ đơn giản nhất có thể là một
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
448

Nhà cung cấp công cụ ước tính hình mờ cho phép các tác giả SDF xác định cách khởi tạo trạng thái hình mờ và tạo công cụ ước tính hình mờ. In Java and this is the

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83. có một loại
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
447 chuyên dụng

Công cụ ước tính thủy vân theo dõi thủy vân khi một cặp hạn chế phần tử đang được tiến hành. Để biết chi tiết về API, hãy đọc tài liệu tham khảo về Java, , và

Có một số triển khai

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 tích hợp sẵn trong Java

  1. Thủ công
  2. tăng đơn điệu
  3. Thời gian tường

Cùng với

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
447 mặc định, có cùng một bộ triển khai
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 tích hợp sẵn trong Python

Các loại

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
446 sau đây được triển khai trong Go

Để xác định SDF, bạn phải chọn xem SDF có giới hạn [mặc định] hay không giới hạn và xác định cách khởi tạo giới hạn ban đầu cho một phần tử. Sự phân biệt dựa trên cách thể hiện khối lượng công việc

  • DoFn có giới hạn là những DoFn mà công việc được đại diện bởi một phần tử đã được biết trước và có kết thúc. Ví dụ về các phần tử được giới hạn bao gồm một tệp hoặc nhóm tệp
  • DoFns không giới hạn là những DoFn mà số lượng công việc không có điểm kết thúc cụ thể hoặc số lượng công việc không được biết trước. Ví dụ về các phần tử không giới hạn bao gồm chủ đề Kafka hoặc PubSub

Trong Java, bạn có thể sử dụng @UnboundedPerElement hoặc @BoundedPerElement để chú thích

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 của mình. Trong Python, bạn có thể sử dụng để chú thích
from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
07

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
08

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
09

Tại thời điểm này, chúng tôi có một SDF hỗ trợ cho phép tái cân bằng công việc động. Để tăng tốc độ xảy ra song song hóa công việc ban đầu hoặc đối với những người chạy không hỗ trợ phân tách do người chạy bắt đầu, chúng tôi khuyên bạn nên cung cấp một tập hợp các lần phân tách ban đầu

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
10

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
11

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
12

12. 2. Định cỡ và tiến độ

Định cỡ và tiến độ được sử dụng trong quá trình thực thi SDF để thông báo cho người chạy để họ có thể thực hiện các quyết định thông minh về việc phân chia những hạn chế nào và cách song song hóa công việc

Trước khi xử lý một phần tử và hạn chế, người chạy có thể sử dụng kích thước ban đầu để chọn cách thức và người xử lý các hạn chế nhằm cải thiện sự cân bằng ban đầu và song song hóa công việc. Trong quá trình xử lý một phần tử và hạn chế, định cỡ và tiến trình được sử dụng để chọn phân chia hạn chế nào và ai sẽ xử lý chúng

Theo mặc định, chúng tôi sử dụng ước tính của trình theo dõi hạn chế cho công việc còn lại dựa trên giả định rằng tất cả các hạn chế đều có chi phí bằng nhau. Để ghi đè mặc định, tác giả SDF có thể cung cấp phương pháp thích hợp trong nhà cung cấp hạn chế. Các tác giả SDF cần lưu ý rằng phương pháp định cỡ sẽ được gọi đồng thời trong quá trình xử lý gói do quá trình phân tách và ước tính tiến độ bắt đầu của người chạy

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
13

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
14

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
15

12. 3. Điểm kiểm tra do người dùng khởi tạo

Một số I/O không thể tạo ra tất cả dữ liệu cần thiết để hoàn thành một hạn chế trong thời gian tồn tại của một gói. Điều này thường xảy ra với các hạn chế không giới hạn, nhưng cũng có thể xảy ra với các hạn chế có giới hạn. For example, there could be more data that needs to be ingested but is not available yet. Một nguyên nhân khác của trường hợp này là do hệ thống nguồn điều chỉnh dữ liệu của bạn

SDF của bạn có thể báo hiệu cho bạn biết rằng bạn chưa xử lý xong hạn chế hiện tại. Tín hiệu này có thể gợi ý thời gian để tiếp tục tại. Trong khi người chạy cố gắng tôn trọng thời gian tiếp tục, điều này không được đảm bảo. Điều này cho phép thực thi tiếp tục trên một hạn chế có sẵn công việc cải thiện việc sử dụng tài nguyên

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
16

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
17

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
18

12. 4. Runner-khởi xướng tách

Người chạy bất cứ lúc nào cũng có thể cố gắng tách một giới hạn trong khi nó đang được xử lý. Điều này cho phép người chạy tạm dừng xử lý hạn chế để có thể thực hiện công việc khác [phổ biến đối với các hạn chế không giới hạn để hạn chế lượng đầu ra và/hoặc cải thiện độ trễ] hoặc chia hạn chế thành hai phần, tăng khả năng song song có sẵn trong hệ thống. vận động viên khác nhau [e. g. , Dataflow, Flink, Spark] có các chiến lược khác nhau để phân tách theo đợt và thực thi trực tuyến

Hãy ghi nhớ điều này khi viết một SDF vì thời điểm kết thúc hạn chế có thể thay đổi. Khi viết vòng lặp xử lý, hãy sử dụng kết quả từ việc cố gắng yêu cầu một phần của hạn chế thay vì cho rằng bạn có thể xử lý cho đến khi kết thúc

Một ví dụ không chính xác có thể là

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
19

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
20

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
21

12. 5. ước tính hình mờ

Công cụ ước tính hình mờ mặc định không tạo ra ước tính hình mờ. Do đó, hình mờ đầu ra chỉ được tính bằng số lượng hình mờ ngược dòng tối thiểu

Một SDF có thể nâng cao hình mờ đầu ra bằng cách chỉ định giới hạn dưới cho tất cả đầu ra trong tương lai mà phần tử này và cặp hạn chế sẽ tạo ra. Người chạy tính toán hình mờ đầu ra tối thiểu bằng cách lấy giá trị tối thiểu trên tất cả các hình mờ ngược dòng và giá trị tối thiểu được báo cáo bởi từng phần tử và cặp giới hạn. Hình mờ được báo cáo phải tăng đơn điệu cho từng phần tử và cặp hạn chế trên các ranh giới gói. Khi một phần tử và cặp hạn chế ngừng xử lý hình mờ của nó, nó không còn được coi là một phần của phép tính trên

Lời khuyên

  • Nếu bạn tạo một SDF xuất các bản ghi có dấu thời gian, bạn nên đưa ra các cách để cho phép người dùng SDF này định cấu hình công cụ ước tính hình mờ nào sẽ sử dụng
  • Bất kỳ dữ liệu nào được tạo ra trước hình mờ có thể được coi là muộn. Xem để biết thêm chi tiết

12. 5. 1. Kiểm soát hình mờ

Có hai loại công cụ ước tính thủy vân chung. quan sát dấu thời gian và quan sát đồng hồ bên ngoài. Công cụ ước tính hình mờ quan sát dấu thời gian sử dụng dấu thời gian đầu ra của mỗi bản ghi để tính toán ước tính hình mờ trong khi công cụ ước tính hình mờ quan sát đồng hồ bên ngoài kiểm soát hình mờ bằng cách sử dụng đồng hồ không được liên kết với bất kỳ đầu ra riêng lẻ nào, chẳng hạn như đồng hồ cục bộ của máy hoặc đồng hồ tiếp xúc

Nhà cung cấp công cụ ước tính hình mờ cho phép bạn ghi đè logic ước tính hình mờ mặc định và sử dụng triển khai công cụ ước tính hình mờ hiện có. Bạn cũng có thể cung cấp triển khai ước tính hình mờ của riêng mình

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
22

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
23

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
24

12. 6. Cắt ngắn trong quá trình thoát nước

Người chạy hỗ trợ đường ống thoát nước cần có khả năng thoát SDF; . Theo mặc định, các hạn chế có giới hạn xử lý phần còn lại của hạn chế trong khi các hạn chế không có giới hạn kết thúc quá trình xử lý tại điểm kiểm tra do SDF bắt đầu tiếp theo hoặc phân tách do người chạy bắt đầu. Bạn có thể ghi đè hành vi mặc định này bằng cách xác định phương thức thích hợp trên trình cung cấp hạn chế

Ghi chú. Sau khi quá trình thoát đường ống bắt đầu và biến đổi hạn chế cắt ngắn được kích hoạt,

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
457 sẽ không được lên lịch lại

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
25

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
26

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
27

12. 7. Quyết toán gói

Hoàn thiện gói cho phép một

from apache_beam.options.pipeline_options import PipelineOptions

beam_options = PipelineOptions[]
83 thực hiện các tác dụng phụ bằng cách đăng ký gọi lại. Cuộc gọi lại được gọi sau khi người chạy đã thừa nhận rằng nó đã duy trì đầu ra một cách lâu dài. Ví dụ: một hàng đợi tin nhắn có thể cần xác nhận các tin nhắn mà nó đã nhập vào đường dẫn. Quyết toán gói không giới hạn ở SDF nhưng được gọi ra ở đây vì đây là trường hợp sử dụng chính

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
28

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
29

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
30

13. Đường ống đa ngôn ngữ

Phần này cung cấp tài liệu toàn diện về các đường dẫn đa ngôn ngữ. Để bắt đầu tạo một kênh dẫn đa ngôn ngữ, hãy xem

  • Khởi động nhanh đường dẫn đa ngôn ngữ Python
  • Khởi động nhanh đường dẫn đa ngôn ngữ Java

Beam cho phép bạn kết hợp các biến đổi được viết bằng bất kỳ ngôn ngữ SDK được hỗ trợ nào [hiện tại là Java và Python] và sử dụng chúng trong một kênh dẫn đa ngôn ngữ. Khả năng này giúp dễ dàng cung cấp chức năng mới đồng thời trong các Apache Beam SDK khác nhau thông qua một chuyển đổi ngôn ngữ chéo duy nhất. Ví dụ: trình kết nối Apache Kafka và chuyển đổi SQL từ SDK Java có thể được sử dụng trong các đường dẫn Python

Các quy trình sử dụng biến đổi từ nhiều ngôn ngữ SDK được gọi là quy trình đa ngôn ngữ

13. 1. Tạo chuyển đổi ngôn ngữ chéo

Để cung cấp các biến đổi được viết bằng một ngôn ngữ cho các quy trình được viết bằng ngôn ngữ khác, Beam sử dụng một dịch vụ mở rộng, dịch vụ này tạo và đưa các đoạn quy trình dành riêng cho ngôn ngữ thích hợp vào quy trình

Trong ví dụ sau, một đường dẫn Beam Python khởi động một dịch vụ mở rộng Java cục bộ để tạo và thêm các đoạn đường dẫn Java thích hợp để thực thi chuyển đổi ngôn ngữ chéo Java Kafka thành đường dẫn Python. SDK sau đó tải xuống và tạo các giai đoạn phụ thuộc Java cần thiết để thực hiện các biến đổi này

Khi chạy, trình chạy Beam sẽ thực thi cả hai phép biến đổi Python và Java để chạy đường dẫn

Trong phần này, chúng tôi sẽ sử dụng KafkaIO. Đọc để minh họa cách tạo chuyển đổi ngôn ngữ chéo cho Java và ví dụ thử nghiệm cho Python

13. 1. 1. Tạo các biến đổi Java đa ngôn ngữ

There are two ways to make Java transforms available to other SDKs

  • lựa chọn 1. Trong một số trường hợp, bạn có thể sử dụng các biến đổi Java hiện có từ các SDK khác mà không cần viết thêm bất kỳ mã Java nào
  • Lựa chọn 2. Bạn có thể sử dụng các biến đổi Java tùy ý từ các SDK khác bằng cách thêm một vài lớp Java
13. 1. 1. 1 Sử dụng các biến đổi Java hiện có mà không cần viết thêm mã Java

Bắt đầu với Beam 2. 34. 0, người dùng SDK Python có thể sử dụng một số biến đổi Java mà không cần viết mã Java bổ sung. Điều này có thể hữu ích trong nhiều trường hợp. Ví dụ

  • Nhà phát triển không quen thuộc với Java có thể cần sử dụng biến đổi Java hiện có từ đường dẫn Python
  • Một nhà phát triển có thể cần cung cấp một biến đổi Java hiện có cho một đường dẫn Python mà không cần viết/phát hành thêm mã Java

Ghi chú. Tính năng này hiện chỉ khả dụng khi sử dụng các biến đổi Java từ một đường dẫn Python

Để đủ điều kiện sử dụng trực tiếp, API của biến đổi Java phải đáp ứng các yêu cầu sau

  1. Biến đổi Java có thể được xây dựng bằng cách sử dụng hàm tạo công khai có sẵn hoặc phương thức tĩnh công khai [phương thức tạo] trong cùng một lớp Java
  2. Biến đổi Java có thể được cấu hình bằng một hoặc nhiều phương thức trình tạo. Mỗi phương thức của trình tạo phải ở chế độ công khai và sẽ trả về một phiên bản của biến đổi Java

Đây là một lớp Java mẫu có thể được sử dụng trực tiếp từ API Python

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
31

Để biết ví dụ hoàn chỉnh, hãy xem JavaDataGenerator

Để sử dụng một lớp Java tuân thủ các yêu cầu trên từ đường dẫn SDK Python, hãy làm theo các bước sau

  1. Tạo danh sách cho phép yaml mô tả các lớp và phương thức biến đổi Java sẽ được truy cập trực tiếp từ Python
  2. Bắt đầu một dịch vụ mở rộng, sử dụng tùy chọn
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    459 để chuyển đường dẫn đến danh sách cho phép
  3. Sử dụng API JavaExternalTransform của Python để truy cập trực tiếp các biến đổi Java được xác định trong danh sách cho phép từ phía Python

Bắt đầu với Beam 2. 36. 0, có thể bỏ qua bước 1 và 2, như được mô tả trong các phần tương ứng bên dưới

Bước 1

Để sử dụng biến đổi Java đủ điều kiện từ Python, hãy xác định danh sách cho phép yaml. Danh sách cho phép này liệt kê tên lớp, phương thức hàm tạo và phương thức trình tạo có sẵn trực tiếp để sử dụng từ phía Python

Bắt đầu với Beam 2. 35. 0, bạn có tùy chọn chuyển

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
006 sang tùy chọn
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
459 thay vì xác định danh sách cho phép thực tế.
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
006 chỉ định rằng tất cả các biến đổi được hỗ trợ trong đường dẫn lớp của dịch vụ mở rộng có thể được truy cập thông qua API. Chúng tôi khuyến khích sử dụng danh sách cho phép thực tế để sản xuất, vì việc cho phép khách hàng truy cập các lớp Java tùy ý có thể gây ra rủi ro bảo mật

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
32

Bước 2

Cung cấp danh sách cho phép làm đối số khi khởi động dịch vụ mở rộng Java. Ví dụ: bạn có thể bắt đầu dịch vụ mở rộng dưới dạng quy trình Java cục bộ bằng cách sử dụng lệnh sau

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
33

Bắt đầu với Beam 2. 36. 0, API

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
463 sẽ tự động khởi động dịch vụ mở rộng với phần phụ thuộc tệp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
464 nhất định nếu địa chỉ dịch vụ mở rộng không được cung cấp

Bước 3

Bạn có thể sử dụng lớp Java trực tiếp từ đường dẫn Python của mình bằng cách sử dụng một biến đổi sơ khai được tạo từ API

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
463. API này cho phép bạn xây dựng biến đổi bằng cách sử dụng tên lớp Java và cho phép bạn gọi các phương thức của trình tạo để định cấu hình lớp

Các loại tham số của hàm tạo và phương thức được ánh xạ giữa Python và Java bằng cách sử dụng lược đồ Beam. Lược đồ được tạo tự động bằng cách sử dụng các loại đối tượng được cung cấp ở phía Python. Nếu phương thức hàm tạo lớp Java hoặc phương thức trình tạo chấp nhận bất kỳ loại đối tượng phức tạp nào, hãy đảm bảo rằng lược đồ Beam cho các đối tượng này đã được đăng ký và sẵn dùng cho dịch vụ mở rộng Java. Nếu lược đồ chưa được đăng ký, dịch vụ mở rộng Java sẽ cố gắng đăng ký lược đồ bằng cách sử dụng. Trong Python, các đối tượng tùy ý có thể được biểu diễn bằng cách sử dụng các

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
052, sẽ được biểu diễn dưới dạng các hàng Beam trong lược đồ. Đây là một biến đổi sơ khai Python đại diện cho biến đổi Java đã đề cập ở trên

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
34

Bạn có thể sử dụng biến đổi này trong một đường dẫn Python cùng với các biến đổi Python khác. Để biết ví dụ hoàn chỉnh, hãy xem javadatagenerator. py

13. 1. 1. 2 Sử dụng API để cung cấp các biến đổi Java hiện có cho các SDK khác

Để làm cho Beam Java SDK của bạn có thể chuyển đổi linh hoạt trên các ngôn ngữ SDK, bạn phải triển khai hai giao diện. ExternalTransformBuilder and ExternalTransformRegistrar. The

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
467 interface constructs the cross-language transform using configuration values passed in from the pipeline, and the
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
468 interface registers the cross-language transform for use with the expansion service

Triển khai các giao diện

  1. Xác định lớp Trình tạo cho phép biến đổi của bạn để triển khai giao diện

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    467 và ghi đè phương thức
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470 sẽ được sử dụng để xây dựng đối tượng biến đổi của bạn. Các giá trị cấu hình ban đầu cho biến đổi của bạn phải được xác định theo phương thức
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470. Trong hầu hết các trường hợp, thật tiện lợi khi làm cho lớp trình tạo biến đổi Java triển khai
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    467

    Ghi chú.

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    467 yêu cầu bạn xác định một đối tượng cấu hình [một POJO đơn giản] để nắm bắt một tập hợp các tham số do SDK bên ngoài gửi để bắt đầu chuyển đổi Java. Thông thường, các tham số này ánh xạ trực tiếp tới các tham số hàm tạo của biến đổi Java

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    35

    Để biết các ví dụ đầy đủ, hãy xem JavaCountBuilder và JavaPrefixBuilder

    Lưu ý rằng phương pháp

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470 có thể thực hiện các thao tác bổ sung trước khi đặt các thuộc tính nhận được từ SDK bên ngoài trong quá trình chuyển đổi. Ví dụ:
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    470 có thể xác thực các thuộc tính có sẵn trong đối tượng cấu hình trước khi đặt chúng trong biến đổi

  2. Đăng ký biến đổi dưới dạng biến đổi ngôn ngữ chéo bên ngoài bằng cách xác định một lớp thực hiện

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    468. Bạn phải chú thích lớp của mình bằng chú thích
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    477 để đảm bảo rằng biến đổi của bạn được đăng ký và khởi tạo đúng cách bởi dịch vụ mở rộng

  3. Trong lớp công ty đăng ký của bạn, hãy xác định Tên tài nguyên thống nhất [URN] cho biến đổi của bạn. URN phải là một chuỗi duy nhất xác định biến đổi của bạn với dịch vụ mở rộng

  4. Từ bên trong lớp công ty đăng ký của bạn, hãy xác định lớp cấu hình cho các tham số được sử dụng trong quá trình khởi tạo chuyển đổi của bạn bằng SDK bên ngoài

    Ví dụ sau đây từ phép biến đổi KafkaIO cho thấy cách thực hiện các bước từ hai đến bốn

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    36

    Để biết thêm ví dụ, hãy xem JavaCountRegistrar và JavaPrefixRegistrar

Sau khi bạn đã triển khai các giao diện

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
467 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
468, biến đổi của bạn có thể được đăng ký và tạo thành công bởi dịch vụ mở rộng Java mặc định

Bắt đầu dịch vụ mở rộng

You can use an expansion service with multiple transforms in the same pipeline. The Beam Java SDK provides a default expansion service for Java transforms. Bạn cũng có thể viết dịch vụ mở rộng của riêng mình, nhưng điều đó thường không cần thiết, vì vậy nó không được đề cập trong phần này

Thực hiện các thao tác sau để khởi động trực tiếp dịch vụ mở rộng Java

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
37

Dịch vụ mở rộng hiện đã sẵn sàng để phục vụ các biến đổi trên cổng được chỉ định

Khi tạo trình bao bọc dành riêng cho SDK cho biến đổi của mình, bạn có thể sử dụng các tiện ích do SDK cung cấp để bắt đầu dịch vụ mở rộng. Ví dụ: SDK Python cung cấp các tiện ích và để khởi động dịch vụ mở rộng Java bằng tệp JAR

bao gồm các phụ thuộc

Nếu biến đổi của bạn yêu cầu các thư viện bên ngoài, bạn có thể đưa chúng vào bằng cách thêm chúng vào đường dẫn lớp của dịch vụ mở rộng. Sau khi chúng được đưa vào đường dẫn lớp, chúng sẽ được phân đoạn khi biến đổi của bạn được mở rộng bởi dịch vụ mở rộng

Viết trình bao bọc dành riêng cho SDK

Chuyển đổi Java ngôn ngữ chéo của bạn có thể được gọi thông qua lớp cấp thấp hơn trong một đường dẫn đa ngôn ngữ [như được mô tả trong phần tiếp theo]; . Sự trừu tượng hóa cấp cao hơn này sẽ giúp các tác giả đường ống sử dụng biến đổi của bạn dễ dàng hơn

Để tạo trình bao bọc SDK để sử dụng trong đường dẫn Python, hãy làm như sau

  1. Tạo một mô-đun Python cho [các] biến đổi ngôn ngữ chéo của bạn

  2. Trong mô-đun, sử dụng một trong các lớp để xây dựng tải trọng cho yêu cầu mở rộng chuyển đổi ngôn ngữ chéo ban đầu

    Tên tham số và loại tải trọng phải ánh xạ tới tên tham số và loại cấu hình POJO được cung cấp cho Java

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    467. Các loại tham số được ánh xạ trên các SDK bằng lược đồ Beam. Tên tham số được ánh xạ bằng cách đơn giản chuyển đổi tên biến được phân tách bằng dấu gạch dưới Python thành trường hợp lạc đà [tiêu chuẩn Java]

    Trong ví dụ sau, kafka. py sử dụng

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    485 để xây dựng tải trọng. Các tham số ánh xạ tới Java KafkaIO. Bên ngoài. Đối tượng cấu hình cấu hình được xác định trong phần trước

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    38

  3. Bắt đầu một dịch vụ mở rộng, trừ khi một dịch vụ được chỉ định bởi người tạo đường ống. Beam Python SDK cung cấp các tiện ích và để khởi động dịch vụ mở rộng bằng tệp JAR. có thể được sử dụng để khởi động dịch vụ mở rộng bằng cách sử dụng đường dẫn [đường dẫn cục bộ hoặc URL] tới tệp JAR đã cho. có thể được sử dụng để bắt đầu dịch vụ mở rộng từ JAR được phát hành với Beam

    Đối với các biến đổi được phát hành bằng Beam, hãy làm như sau

    1. Thêm mục tiêu Gradle vào Beam có thể được sử dụng để xây dựng JAR dịch vụ mở rộng bóng mờ cho biến đổi Java mục tiêu. Mục tiêu này sẽ tạo ra một Beam JAR chứa tất cả các phụ thuộc cần thiết để mở rộng biến đổi Java và JAR sẽ được phát hành cùng với Beam. Bạn có thể sử dụng mục tiêu Gradle hiện có cung cấp phiên bản tổng hợp của dịch vụ mở rộng JAR [ví dụ: cho tất cả GCP IO]

    2. Trong mô-đun Python của bạn, hãy khởi tạo

      import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      481 với mục tiêu Gradle

      await beam.createRunner[].run[function pipeline[root] {
        // Use root to build a pipeline.
      }];
      
      39

  4. Thêm một lớp biến đổi trình bao bọc Python mở rộng. Truyền tải trọng và dịch vụ mở rộng được định nghĩa ở trên dưới dạng tham số cho hàm tạo của lớp cha

13. 1. 2. Tạo các biến đổi Python đa ngôn ngữ

Bất kỳ biến đổi Python nào được xác định trong phạm vi của dịch vụ mở rộng đều có thể truy cập được bằng cách chỉ định tên đủ điều kiện của chúng. Ví dụ: bạn có thể sử dụng biến đổi

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
493 của Python trong một đường ống dẫn Java với tên đủ điều kiện của nó là
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
494

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
40

Note.

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
495 có các phương pháp hữu ích khác như
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
496 để dàn dựng các phụ thuộc gói PyPI và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
497 để đặt bộ mã hóa đầu ra

Ngoài ra, bạn có thể muốn tạo một mô-đun Python đăng ký một biến đổi Python hiện có dưới dạng một biến đổi ngôn ngữ chéo để sử dụng với dịch vụ mở rộng Python và gọi vào biến đổi hiện có đó để thực hiện thao tác dự định của nó. Một URN đã đăng ký có thể được sử dụng sau này trong yêu cầu mở rộng để chỉ ra mục tiêu mở rộng

Xác định mô-đun Python

  1. Xác định Tên tài nguyên thống nhất [URN] cho biến đổi của bạn. URN phải là một chuỗi duy nhất xác định biến đổi của bạn với dịch vụ mở rộng

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    41

  2. Đối với một biến đổi Python hiện có, hãy tạo một lớp mới để đăng ký URN với dịch vụ mở rộng Python

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    42

  3. Từ bên trong lớp, định nghĩa một phương thức mở rộng lấy PCollection đầu vào, chạy biến đổi Python, sau đó trả về PCollection đầu ra

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    43

  4. Như với các biến đổi Python khác, hãy xác định phương thức

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    498 trả về URN

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    44

  5. Xác định một phương thức tĩnh

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    499 trả về một khởi tạo của biến đổi Python đa ngôn ngữ

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    45

Bắt đầu dịch vụ mở rộng

Một dịch vụ mở rộng có thể được sử dụng với nhiều biến đổi trong cùng một đường ống. Beam Python SDK cung cấp dịch vụ mở rộng mặc định để bạn sử dụng với các biến đổi Python của mình. Bạn có thể tự do viết dịch vụ mở rộng của riêng mình, nhưng điều đó thường không cần thiết, vì vậy nó không được đề cập trong phần này

Thực hiện các bước sau để khởi động trực tiếp dịch vụ mở rộng Python mặc định

  1. Tạo một môi trường ảo và cài đặt Apache Beam SDK

  2. Start the Python SDK’s expansion service with a specified port

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    46

  3. Nhập bất kỳ mô-đun nào có chứa các biến đổi sẽ được cung cấp bằng dịch vụ mở rộng

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    47

  4. Dịch vụ mở rộng này hiện đã sẵn sàng để phục vụ các biến đổi trên địa chỉ

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    500

bao gồm các phụ thuộc

Hiện tại, các phép biến đổi bên ngoài của Python bị giới hạn ở các phần phụ thuộc có sẵn trong bộ khai thác Beam SDK cốt lõi

13. 1. 3. Tạo biến đổi ngôn ngữ chéo

Go hiện không hỗ trợ tạo biến đổi ngôn ngữ chéo, chỉ sử dụng biến đổi ngôn ngữ chéo từ các ngôn ngữ khác;

13. 1. 4. Định nghĩa một URN

Phát triển chuyển đổi ngôn ngữ chéo liên quan đến việc xác định URN để đăng ký chuyển đổi với dịch vụ mở rộng. Trong phần này, chúng tôi cung cấp một quy ước để xác định các URN như vậy. Việc tuân theo quy ước này là tùy chọn nhưng nó sẽ đảm bảo rằng biến đổi của bạn sẽ không gặp xung đột khi đăng ký dịch vụ mở rộng cùng với các biến đổi do các nhà phát triển khác phát triển

13. 1. 4. 1. Lược đồ

Một URN nên bao gồm các thành phần sau

  • ns-id. Một định danh không gian tên. Đề xuất mặc định là
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    501
  • định danh tổ chức. Xác định tổ chức nơi chuyển đổi được xác định. Các biến đổi được xác định trong Apache Beam sử dụng
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    502 cho việc này
  • định danh chức năng. Xác định chức năng của chuyển đổi ngôn ngữ chéo
  • phiên bản. một số phiên bản cho chuyển đổi

Chúng tôi cung cấp lược đồ từ quy ước URN ở dạng Backus–Naur tăng cường. Từ khóa trong chữ hoa là từ thông số URN

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
48

13. 1. 4. 2. ví dụ

Dưới đây chúng tôi đã đưa ra một số ví dụ về các lớp biến đổi và các URN tương ứng sẽ được sử dụng

  • Một biến đổi được cung cấp với Apache Beam để ghi các tệp Parquet
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      503
  • Một biến đổi được cung cấp với Apache Beam đọc từ Kafka với siêu dữ liệu
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      504
  • Một biến đổi được phát triển bởi tổ chức abc. org đọc từ kho dữ liệu MyDatastore
    • import apache_beam as beam
      
      with beam.Pipeline[] as pipeline:
        pass  # build your pipeline here
      505

13. 2. Sử dụng biến đổi ngôn ngữ chéo

Depending on the SDK language of the pipeline, you can use a high-level SDK-wrapper class, or a low-level transform class to access a cross-language transform

13. 2. 1. Sử dụng các biến đổi ngôn ngữ chéo trong một đường dẫn Java

Người dùng có ba tùy chọn để sử dụng chuyển đổi ngôn ngữ chéo trong đường dẫn Java. Ở mức độ trừu tượng cao nhất, một số biến đổi Python phổ biến có thể truy cập được thông qua các biến đổi trình bao bọc Java chuyên dụng. Ví dụ: SDK Java có lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
506, lớp này sử dụng lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
506 của SDK Python và lớp này có lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
508, lớp này sử dụng lớp
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
508 của SDK Python, v.v. Khi biến đổi trình bao bọc dành riêng cho SDK không có sẵn cho biến đổi Python đích, bạn có thể sử dụng lớp PythonExternalTransform cấp thấp hơn thay vào đó bằng cách chỉ định tên đủ điều kiện của biến đổi Python. Nếu bạn muốn thử chuyển đổi bên ngoài từ SDK khác ngoài Python [bao gồm cả SDK Java], bạn cũng có thể sử dụng lớp Bên ngoài cấp thấp nhất

Sử dụng trình bao bọc SDK

Để sử dụng chuyển đổi ngôn ngữ chéo thông qua trình bao bọc SDK, hãy nhập mô-đun cho trình bao bọc SDK và gọi nó từ quy trình của bạn, như minh họa trong ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
49

Sử dụng lớp PythonExternalTransform

Khi không có trình bao bọc dành riêng cho SDK, bạn có thể truy cập biến đổi đa ngôn ngữ Python thông qua lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
495 bằng cách chỉ định tên đủ điều kiện và đối số hàm tạo của biến đổi Python đích

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
50

Sử dụng lớp bên ngoài

  1. Đảm bảo rằng bạn đã cài đặt mọi phụ thuộc môi trường thời gian chạy [như JRE] trên máy cục bộ của mình [trực tiếp trên máy cục bộ hoặc có sẵn thông qua bộ chứa]. Xem phần dịch vụ mở rộng để biết thêm chi tiết

    Ghi chú. Khi bao gồm các biến đổi Python từ bên trong đường dẫn Java, tất cả các phần phụ thuộc Python phải được bao gồm trong bộ chứa khai thác SDK

  2. Bắt đầu dịch vụ mở rộng cho SDK bằng ngôn ngữ của biến đổi mà bạn đang cố gắng sử dụng, nếu không có sẵn

    Đảm bảo rằng biến đổi bạn đang cố sử dụng có sẵn và có thể được sử dụng bởi dịch vụ mở rộng

  3. Include External. of[…] khi khởi tạo đường dẫn của bạn. Tham khảo dịch vụ URN, tải trọng và mở rộng. Ví dụ, xem bộ thử nghiệm chuyển đổi ngôn ngữ chéo

  4. Sau khi công việc đã được gửi tới trình chạy Beam, hãy tắt dịch vụ mở rộng bằng cách chấm dứt quy trình dịch vụ mở rộng

13. 2. 2. Sử dụng các biến đổi ngôn ngữ chéo trong một đường dẫn Python

Nếu có trình bao bọc dành riêng cho Python cho biến đổi ngôn ngữ chéo, hãy sử dụng trình bao bọc đó. Mặt khác, bạn phải sử dụng lớp cấp thấp hơn để truy cập biến đổi

Sử dụng trình bao bọc SDK

Để sử dụng chuyển đổi ngôn ngữ chéo thông qua trình bao bọc SDK, hãy nhập mô-đun cho trình bao bọc SDK và gọi nó từ quy trình của bạn, như minh họa trong ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
51

Sử dụng lớp ExternalTransform

Khi không có trình bao bọc dành riêng cho SDK, bạn sẽ phải truy cập vào chuyển đổi ngôn ngữ chéo thông qua lớp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
482

  1. Đảm bảo rằng bạn đã cài đặt mọi phụ thuộc môi trường thời gian chạy [như JRE] trên máy cục bộ của mình. Xem phần dịch vụ mở rộng để biết thêm chi tiết

  2. Bắt đầu dịch vụ mở rộng cho SDK bằng ngôn ngữ của biến đổi mà bạn đang cố gắng sử dụng, nếu không có sẵn. Python cung cấp một số lớp để tự động bắt đầu các dịch vụ java mở rộng, chẳng hạn như và có thể được chuyển trực tiếp dưới dạng dịch vụ mở rộng tới

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    513. Đảm bảo rằng biến đổi bạn đang cố sử dụng có sẵn và có thể được sử dụng bởi dịch vụ mở rộng

    Đối với Java, đảm bảo rằng trình xây dựng và công ty đăng ký cho biến đổi có sẵn trong đường dẫn lớp của dịch vụ mở rộng

  3. Bao gồm

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    482 khi khởi tạo quy trình bán hàng của bạn. Tham khảo dịch vụ URN, tải trọng và mở rộng. Bạn có thể sử dụng một trong các lớp có sẵn để xây dựng tải trọng cho
    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    482

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    52

    For additional examples, see addprefix. py and javacount. py

  4. After the job has been submitted to the Beam runner, shut down any manually started expansion services by terminating the expansion service process

Using the JavaExternalTransform class

Python has the ability to invoke Java-defined transforms via as if they were Python transforms. These are invoked as follows

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
53

Python’s

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
517 method can be used if the method names in java are reserved Python keywords such as
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
518

As with other external transforms, either a pre-started expansion service can be provided, or jar files that include the transform, its dependencies, and Beam’s expansion service in which case an expansion service will be auto-started

13. 2. 3. Using cross-language transforms in a Go pipeline

If a Go-specific wrapper for a cross-language is available, use that. Otherwise, you have to use the lower-level function to access the transform

Expansion Services

The Go SDK supports automatically starting Java expansion services if an expansion address is not provided, although this is slower than providing a persistent expansion service. Many wrapped Java transforms manage perform this automatically; if you wish to do this manually, use the

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
519 package’s function. In order to use Python cross-language transforms, you must manually start any necessary expansion services on your local machine and ensure they are accessible to your code during pipeline construction

Sử dụng trình bao bọc SDK

To use a cross-language transform through an SDK wrapper, import the package for the SDK wrapper and call it from your pipeline as shown in the example

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
54

Using the CrossLanguage function

Khi không có trình bao bọc dành riêng cho SDK, bạn sẽ phải truy cập vào chuyển đổi ngôn ngữ chéo thông qua chức năng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
520

  1. Đảm bảo bạn có dịch vụ mở rộng phù hợp đang chạy. Xem phần dịch vụ mở rộng để biết chi tiết

  2. Đảm bảo rằng biến đổi bạn đang cố sử dụng có sẵn và có thể được sử dụng bởi dịch vụ mở rộng. Tham khảo để biết chi tiết

  3. Sử dụng chức năng

    import apache_beam as beam
    
    with beam.Pipeline[] as pipeline:
      pass  # build your pipeline here
    520 trong quy trình của bạn khi thích hợp. Tham khảo URN, tải trọng, địa chỉ dịch vụ mở rộng và xác định đầu vào và đầu ra. Bạn có thể sử dụng chức năng này như một công cụ trợ giúp để mã hóa tải trọng. Bạn có thể sử dụng các hàm và làm lối tắt cho các đầu vào/đầu ra đơn lẻ, không tên hoặc xác định bản đồ cho các đầu vào/đầu ra được đặt tên

    await beam.createRunner[].run[function pipeline[root] {
      // Use root to build a pipeline.
    }];
    
    55

  4. Sau khi công việc đã được gửi tới trình chạy Beam, hãy tắt dịch vụ mở rộng bằng cách chấm dứt quy trình dịch vụ mở rộng

13. 2. 4. Sử dụng các biến đổi ngôn ngữ chéo trong một đường ống Bản mô tả

Việc sử dụng trình bao bọc Bản mô tả cho đường dẫn ngôn ngữ chéo cũng tương tự như sử dụng bất kỳ biến đổi nào khác, miễn là các phụ thuộc [e. g. một trình thông dịch Python gần đây hoặc Java JRE] có sẵn. Ví dụ: hầu hết các IO Bản mô tả chỉ đơn giản là các trình bao bọc xung quanh các biến đổi Beam từ các ngôn ngữ khác

Nếu trình bao bọc chưa có sẵn, người ta có thể sử dụng nó một cách rõ ràng bằng cách sử dụng apache_beam. biến đổi. bên ngoài. rawExternalTransform. lấy `urn` [chuỗi xác định biến đổi], `payload` [đối tượng nhị phân hoặc json tham số hóa biến đổi] và `expansionService` có thể là địa chỉ của dịch vụ bắt đầu trước hoặc trả về có thể gọi được

Ví dụ, người ta có thể viết

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
56

Lưu ý rằng

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
522 phải có bộ mã hóa tương thích đa ngôn ngữ, chẳng hạn như
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
523. Điều này có thể được đảm bảo với các biến đổi withCoderInternal hoặc withRowCoder, e. g

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
57

Coder cũng có thể được chỉ định trên đầu ra nếu nó không thể được suy ra, e. g

Ngoài ra, có một số tiện ích như pythonTransform giúp gọi các phép biến đổi từ các ngôn ngữ cụ thể dễ dàng hơn

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
58

Chuyển đổi ngôn ngữ chéo cũng có thể được xác định theo dòng, có thể hữu ích để truy cập các tính năng hoặc thư viện không có sẵn trong SDK gọi

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
59

13. 3. Hỗ trợ người chạy

Hiện tại, các trình chạy di động như Flink, Spark và trình chạy trực tiếp có thể được sử dụng với các đường dẫn đa ngôn ngữ

Dataflow hỗ trợ các đường ống đa ngôn ngữ thông qua kiến ​​trúc phụ trợ Dataflow Runner v2

13. 4 mẹo và khắc phục sự cố

Để biết thêm mẹo và thông tin khắc phục sự cố, hãy xem tại đây

14 Batched DoFns

Thích ứng cho
  • SDK Java
  • SDK Python
  • Truy cập SDK
  • SDK TypeScript

Batched DoFns hiện là một tính năng chỉ dành cho Python

Batched DoFns cho phép người dùng tạo các thành phần mô-đun, có thể kết hợp hoạt động theo lô gồm nhiều thành phần logic. Các DoFn này có thể tận dụng các thư viện Python được vector hóa, như numpy, scipy và pandas, hoạt động trên các lô dữ liệu để đạt hiệu quả

14. 1 Khái niệm cơ bản

Batched DoFns hiện là một tính năng chỉ dành cho Python

Một Batched DoFn tầm thường có thể trông như thế này

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
60

DoFn này có thể được sử dụng trong đường ống Beam hoạt động trên các phần tử riêng lẻ. Beam sẽ hoàn toàn đệm các phần tử và tạo các mảng có nhiều mảng ở phía đầu vào và ở phía đầu ra, nó sẽ phân tách các mảng có nhiều mảng thành các phần tử riêng lẻ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
61

Lưu ý rằng chúng tôi sử dụng để đặt kiểu chữ khôn ngoan cho đầu ra của

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
525. Sau đó, khi áp dụng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
526 cho
await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
73 này, Beam nhận ra rằng
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
528 là loại lô có thể chấp nhận được để sử dụng cùng với các phần tử
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
529. Chúng tôi sẽ sử dụng các gợi ý kiểu chữ gọn gàng như thế này trong suốt hướng dẫn này, nhưng Beam cũng hỗ trợ các gợi ý kiểu chữ từ các thư viện khác, hãy xem

Trong trường hợp trước, Beam sẽ ngầm tạo và phát nổ các lô ở ranh giới đầu vào và đầu ra. Tuy nhiên, nếu Batched DoFns với các loại tương đương được xâu chuỗi lại với nhau, việc tạo và phát nổ hàng loạt này sẽ bị loại bỏ. Các lô sẽ được chuyển thẳng qua. Điều này làm cho việc tổng hợp hiệu quả các biến đổi hoạt động theo lô trở nên đơn giản hơn nhiều

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
62

14. Dự phòng 2 phần tử

Batched DoFns hiện là một tính năng chỉ dành cho Python

Đối với một số DoFns, bạn có thể cung cấp cả triển khai theo đợt và theo từng phần tử theo logic mong muốn của mình. Bạn có thể làm điều này bằng cách xác định cả

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
531

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
63

Khi thực hiện DoFn này, Beam sẽ chọn cách triển khai tốt nhất để sử dụng trong bối cảnh nhất định. Nói chung, nếu các đầu vào cho DoFn đã được theo đợt thì Beam sẽ sử dụng triển khai theo đợt;

Lưu ý rằng, trong trường hợp này, không cần xác định

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
533. Điều này là do Beam có thể lấy loại đầu ra từ gợi ý đánh máy trên
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30

14. 3 Sản xuất hàng loạt so với. tiêu thụ hàng loạt

Batched DoFns hiện là một tính năng chỉ dành cho Python

Theo quy ước, Beam giả định rằng phương pháp

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
531, sử dụng các đầu vào theo đợt, cũng sẽ tạo ra các đầu ra theo đợt. Tương tự, Beam giả sử phương pháp
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 sẽ tạo ra các phần tử riêng lẻ. Điều này có thể được ghi đè bằng và trang trí. Ví dụ

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
64

14. 4 loại lô được hỗ trợ

Batched DoFns hiện là một tính năng chỉ dành cho Python

Chúng tôi đã sử dụng các loại numpy trong triển khai Batched DoFn trong hướng dẫn này –

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
539 làm gợi ý kiểu phần tử và
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
528 làm gợi ý kiểu lô tương ứng – nhưng Beam cũng hỗ trợ các gợi ý kiểu chữ từ các thư viện khác

cục mịch

Gợi ý Kiểu phần tửGợi ý Kiểu hàng loạtCác kiểu số [
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
542,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
543,…] np. ndarray [của Mảng Numpy]

gấu trúc

Loại phần tửgợi ýLoại hàng loạtgợi ýCác loại số [
// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
01,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
542,
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
543,…]
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
547_______54_______548
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
057
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
550

Other types?

Nếu có các loại lô khác mà bạn muốn sử dụng với Batched DoFns, vui lòng gửi vấn đề

14. 5 loại đầu vào và đầu ra hàng loạt động

Batched DoFns hiện là một tính năng chỉ dành cho Python

Đối với một số DoFns theo lô, có thể không đủ để khai báo các loại lô một cách tĩnh, với gợi ý đánh máy trên

// If beamx or Go flags are used, flags must be parsed first,
// before beam.Init[] is called.
flag.Parse[]
30 và/hoặc
import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
531. Bạn có thể cần phải khai báo động các kiểu này. Bạn có thể thực hiện việc này bằng cách ghi đè các phương thức và trên DoFn của mình

await beam.createRunner[].run[function pipeline[root] {
  // Use root to build a pipeline.
}];
65

14. 6 lô và ngữ nghĩa thời gian sự kiện

Batched DoFns hiện là một tính năng chỉ dành cho Python

Hiện tại, các lô phải có một bộ thông tin thời gian duy nhất [thời gian sự kiện, cửa sổ, v.v.] áp dụng cho mọi thành phần logic trong lô. Hiện tại không có cơ chế để tạo các lô kéo dài nhiều dấu thời gian. Tuy nhiên, có thể truy xuất thông tin thời gian này trong triển khai Batched DoFn. Thông tin này có thể được truy cập bằng cách sử dụng các thuộc tính

import apache_beam as beam

with beam.Pipeline[] as pipeline:
  pass  # build your pipeline here
555 thông thường

Chủ Đề