Skip to content

Commit 694a01e

Browse files
committed
Read events from one family
1 parent 00901cd commit 694a01e

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

repository/repository.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ func (r *Repository) Read(ctx context.Context, key string) (*data.Set, error) {
5555
return r.read(ctx, key)
5656
}
5757

58+
/*
59+
ReadFamily reads a row from the repository keeping only the desired column family and map it to a data.Set
60+
61+
This method takes a row key and the column family as an argument, uses its internal adapter to read the row from Big Table,
62+
parses all cells contained in the row to turn it into a map of data.Event and finally returns the data.Set that contains all the events.
63+
64+
Be careful, this method will perform an exact match on the column family name.
65+
*/
66+
func (r *Repository) ReadFamily(ctx context.Context, key string, family string) (*data.Set, error) {
67+
familyFilter := bigtable.RowFilter(bigtable.FamilyFilter(family))
68+
return r.read(ctx, key, familyFilter)
69+
}
70+
5871
// ReadLast reads a row from the repository while returning only the latest cell values after
5972
// mapping it to a data.Set. This method takes a row key as an argument, uses its internal adapter
6073
// to read the row from Big Table, parses only the latest cells contained in the row to turn it into

repository/repository_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,68 @@ func ExampleRepository_ReadLast() {
332332
// Smartphone
333333
}
334334

335+
func ExampleRepository_ReadFamily() {
336+
ctx := context.Background()
337+
client := getBigTableClient(ctx)
338+
c, err := fs.ReadFile("testdata/mapping.json")
339+
if err != nil {
340+
log.Fatalln(err)
341+
}
342+
jsonMapping, err := mapping.LoadMapping(c)
343+
if err != nil {
344+
log.Fatalln(err)
345+
}
346+
mapper := mapping.NewMapper(jsonMapping)
347+
tbl := client.Open(table)
348+
349+
repo := NewRepository(tbl, mapper)
350+
eventSet := &data.Set{Events: map[string][]*data.Event{
351+
"front": {
352+
{
353+
RowKey: "contactz-102",
354+
Date: time.Date(2018, time.January, 1, 0, 2, 0, 0, time.UTC),
355+
Cells: map[string]string{
356+
"event_type": "add_to_cart",
357+
"device_type": "Computer",
358+
"url": "https://example.org/some/product",
359+
},
360+
},
361+
},
362+
"blog": {
363+
{
364+
RowKey: "contactz-102",
365+
Date: time.Date(2018, time.January, 1, 0, 2, 0, 0, time.UTC),
366+
Cells: map[string]string{
367+
"event_type": "page_view",
368+
"device_type": "Computer",
369+
"url": "https://example.org/blog/article/1",
370+
},
371+
},
372+
},
373+
}}
374+
375+
// insert
376+
errs, err := repo.Write(ctx, eventSet)
377+
if err != nil {
378+
log.Fatalln(err)
379+
}
380+
if len(errs) > 0 {
381+
log.Fatalln(errs)
382+
}
383+
384+
readSet, err := repo.ReadFamily(ctx, "contactz-102", "blog")
385+
if err != nil {
386+
log.Fatalln(err)
387+
}
388+
for _, event := range readSet.Events["blog"] {
389+
fmt.Println(event.Cells["event_type"])
390+
fmt.Println(event.Cells["device_type"])
391+
}
392+
// Output:
393+
// page_view
394+
// Computer
395+
}
396+
335397
var t1 = bigtable.Time(time.Date(2020, time.January, 1, 0, 1, 0, 0, time.UTC))
336398
var t2 = bigtable.Time(time.Date(2020, time.January, 1, 0, 2, 0, 0, time.UTC))
337399
var t3 = bigtable.Time(time.Date(2020, time.January, 1, 0, 3, 0, 0, time.UTC))
@@ -489,6 +551,57 @@ func TestRepository_ReadLast(t *testing.T) {
489551
}
490552
}
491553

554+
func TestRepository_ReadFamily(t *testing.T) {
555+
ctx := context.Background()
556+
repository := &Repository{
557+
adapter: mockAdapter{},
558+
mapper: getMockMapper(t),
559+
}
560+
eventSet, err := repository.ReadFamily(ctx, "contact-3", "front")
561+
if err != nil {
562+
t.Fatalf("failed to read: %v", err)
563+
}
564+
if len(eventSet.Events) != 1 {
565+
t.Fatalf("expected 1 event family, got %d", len(eventSet.Events))
566+
}
567+
if v, ok := eventSet.Events["front"]; !ok {
568+
t.Fatalf("expected front family, got %v", v)
569+
} else {
570+
if len(v) != 3 {
571+
t.Fatalf("expected 3 events, got %d", len(v))
572+
}
573+
574+
if v[0].RowKey != "contact-3" {
575+
t.Fatalf("expected contact-3, got %s", v[0].RowKey)
576+
}
577+
if v[0].Cells["url"] != "http://someexample.url/query/string/1" {
578+
t.Fatalf("expected http://someexample.url/query/string/1, got %s", v[0].Cells["url"])
579+
}
580+
if v[0].Cells["device_type"] != "Smartphone" {
581+
t.Fatalf("expected Smartphone, got %s", v[0].Cells["device_type"])
582+
}
583+
// here we're testing each event_type depending on the timestamp.
584+
// It's because Go doesn't guarantee the order of the map iteration
585+
for _, event := range v {
586+
if event.Date.Unix() == t1.Time().Unix() {
587+
if event.Cells["event_type"] != "page_view" {
588+
t.Fatalf("expected page_view, got %s", event.Cells["event_type"])
589+
}
590+
}
591+
if event.Date.Unix() == t2.Time().Unix() {
592+
if event.Cells["event_type"] != "add_to_cart" {
593+
t.Fatalf("expected add_to_cart, got %s", event.Cells["event_type"])
594+
}
595+
}
596+
if event.Date.Unix() == t3.Time().Unix() {
597+
if event.Cells["event_type"] != "purchase" {
598+
t.Fatalf("expected purchase, got %s", event.Cells["event_type"])
599+
}
600+
}
601+
}
602+
}
603+
}
604+
492605
//go:embed testdata/mapping.json
493606
var fs embed.FS
494607

@@ -626,6 +739,10 @@ func getBigTableClient(ctx context.Context) *bigtable.Client {
626739
log.Fatalln(err)
627740
}
628741

742+
if err = adminClient.CreateColumnFamily(ctx, table, "blog"); err != nil {
743+
log.Fatalln(err)
744+
}
745+
629746
client, err := bigtable.NewClient(ctx, projectID, instance, option.WithGRPCConn(conn))
630747
if err != nil {
631748
log.Fatalln(err)

0 commit comments

Comments
 (0)