Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add filter #274

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/basic/basic.int.v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ sources:
alternativeIndices:
- 6
- name: Person
filter:
expr: (Record[1] == "Mahinda" or Record[1] == "Michael") and Record[3] == "male"
id:
type: "INT"
index: 0
Expand Down Expand Up @@ -125,6 +127,8 @@ sources:
nullValue: _NULL_
defaultValue: 0000-00-00T00:00:00
- name: KNOWS # person_knows_person
filter:
expr: Record[1] == "XXX"
src:
id:
type: "INT"
Expand Down
66 changes: 66 additions & 0 deletions examples/basic/basic.string.v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,73 @@ sources:
- name: "browserUsed"
type: "STRING"
index: 7
- path: ./person.csv
filter:
expr: Record[1] != "933"
csv:
delimiter: "|"
tags:
- name: Person
id:
type: "STRING"
concatItems:
- person_
- 0
- _id
props:
- name: "firstName"
type: "STRING"
index: 1
- name: "lastName"
type: "STRING"
index: 2
- name: "gender"
type: "STRING"
index: 3
nullable: true
defaultValue: female
- name: "birthday"
type: "DATE"
index: 4
nullable: true
nullValue: _NULL_
- name: "creationDate"
type: "DATETIME"
index: 5
- name: "locationIP"
type: "STRING"
index: 6
- name: "browserUsed"
type: "STRING"
index: 7
- path: ./knows.csv
batch: 256
edges:
- name: KNOWS # person_knows_person
src:
id:
type: "STRING"
concatItems:
- person_
- 0
- _id
dst:
id:
type: "STRING"
concatItems:
- person_
- 1
- _id
props:
- name: "creationDate"
type: "DATETIME"
index: 2
nullable: true
nullValue: _NULL_
defaultValue: 0000-00-00T00:00:00
- path: ./knows.csv
filter:
expr: Record[1] == "XXX"
batch: 256
edges:
- name: KNOWS # person_knows_person
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.19
require (
github.com/agiledragon/gomonkey/v2 v2.9.0
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible
github.com/antonmedv/expr v1.12.5
github.com/aws/aws-sdk-go v1.44.178
github.com/cenkalti/backoff/v4 v4.1.3
github.com/colinmarc/hdfs/v2 v2.3.0
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ github.com/agiledragon/gomonkey/v2 v2.9.0 h1:PDiKKybR596O6FHW+RVSG0Z7uGCBNbmbUXh
github.com/agiledragon/gomonkey/v2 v2.9.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible h1:KXeJoM1wo9I/6xPTyt6qCxoSZnmASiAjlrr0dyTUKt8=
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/antonmedv/expr v1.12.5 h1:Fq4okale9swwL3OeLLs9WD9H6GbgBLJyN/NUHRv+n0E=
github.com/antonmedv/expr v1.12.5/go.mod h1:FPC8iWArxls7axbVLsW+kpg1mz29A1b2M6jt+hZfDkU=
github.com/aws/aws-sdk-go v1.44.178 h1:4igreoWPEA7xVLnOeSXLhDXTsTSPKQONZcQ3llWAJw0=
github.com/aws/aws-sdk-go v1.44.178/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
Expand Down Expand Up @@ -218,11 +220,14 @@ github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUq
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
Expand Down
4 changes: 4 additions & 0 deletions integration-testing/testdata/basic/basic.int.v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ sources:
alternativeIndices:
- 6
- name: Person
filter:
expr: (Record[1] == "Mahinda" or Record[1] == "Michael") and Record[3] == "male"
id:
type: "INT"
index: 0
Expand Down Expand Up @@ -125,6 +127,8 @@ sources:
nullValue: _NULL_
defaultValue: 0000-00-00T00:00:00
- name: KNOWS # person_knows_person
filter:
expr: Record[1] == "XXX"
src:
id:
type: "INT"
Expand Down
66 changes: 66 additions & 0 deletions integration-testing/testdata/basic/basic.string.v3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,73 @@ sources:
- name: "browserUsed"
type: "STRING"
index: 7
- path: ./person.csv
filter:
expr: Record[1] != "933"
csv:
delimiter: "|"
tags:
- name: Person
id:
type: "STRING"
concatItems:
- person_
- 0
- _id
props:
- name: "firstName"
type: "STRING"
index: 1
- name: "lastName"
type: "STRING"
index: 2
- name: "gender"
type: "STRING"
index: 3
nullable: true
defaultValue: female
- name: "birthday"
type: "DATE"
index: 4
nullable: true
nullValue: _NULL_
- name: "creationDate"
type: "DATETIME"
index: 5
- name: "locationIP"
type: "STRING"
index: 6
- name: "browserUsed"
type: "STRING"
index: 7
- path: ./knows.csv
batch: 256
edges:
- name: KNOWS # person_knows_person
src:
id:
type: "STRING"
concatItems:
- person_
- 0
- _id
dst:
id:
type: "STRING"
concatItems:
- person_
- 1
- _id
props:
- name: "creationDate"
type: "DATETIME"
index: 2
nullable: true
nullValue: _NULL_
defaultValue: 0000-00-00T00:00:00
- path: ./knows.csv
filter:
expr: Record[1] == "XXX"
batch: 256
edges:
- name: KNOWS # person_knows_person
Expand Down
1 change: 1 addition & 0 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ var (
ErrNoIndicesOrConcatItems = stderrors.New("no indices or concat items")
ErrUnsupportedConcatItemType = stderrors.New("unsupported concat item type")
ErrUnsupportedFunction = stderrors.New("unsupported function")
ErrFilterSyntax = stderrors.New("filter syntax")
)
2 changes: 1 addition & 1 deletion pkg/errors/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (e *ImportError) Error() string {
fields = append(fields, fmt.Sprintf("%s(%s)", fieldStatement, statement))
}
if len(e.Messages) > 0 {
fields = append(fields, fmt.Sprintf("%s%s", fieldMessages, strings.Join(e.Messages, ", ")))
fields = append(fields, fmt.Sprintf("%s: %s", fieldMessages, strings.Join(e.Messages, ", ")))
}
if e.Err != nil {
fields = append(fields, e.Err.Error())
Expand Down
2 changes: 1 addition & 1 deletion pkg/errors/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ var _ = Describe("ImportError", func() {
"record": []string{"record1", "record2"},
"statement": "test statement",
}))
Expect(importError.Error()).To(Equal("graph(graphName): node(nodeName): edge(edgeName): nodeID(nodeIDName): prop(propName): record([record1 record2]): statement(test statement): messagestest message, test message 1: test error"))
Expect(importError.Error()).To(Equal("graph(graphName): node(nodeName): edge(edgeName): nodeID(nodeIDName): prop(propName): record([record1 record2]): statement(test statement): messages: test message, test message 1: test error"))
})

It("withField", func() {
Expand Down
16 changes: 11 additions & 5 deletions pkg/importer/importer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ type (
}

ImportResp struct {
Latency time.Duration
RespTime time.Duration
RecordNum int
Latency time.Duration
RespTime time.Duration
}

ImportResult struct {
Expand Down Expand Up @@ -96,11 +97,15 @@ func WithWaitFunc(fn func()) Option {
}

func (i *defaultImporter) Import(records ...spec.Record) (*ImportResp, error) {
statement, err := i.builder.Build(records...)
statement, nRecord, err := i.builder.Build(records...)
if err != nil {
return nil, err
}

if nRecord == 0 {
return &ImportResp{}, nil
}

resp, err := i.pool.Execute(statement)
if err != nil {
return nil, errors.NewImportError(err).
Expand All @@ -112,8 +117,9 @@ func (i *defaultImporter) Import(records ...spec.Record) (*ImportResp, error) {
}

return &ImportResp{
RespTime: resp.GetRespTime(),
Latency: resp.GetLatency(),
RecordNum: nRecord,
RespTime: resp.GetRespTime(),
Latency: resp.GetLatency(),
}, nil
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/importer/importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var _ = Describe("Importer", func() {

Describe("New", func() {
It("build failed", func() {
mockBuilder.EXPECT().Build(gomock.Any()).Return("", errors.ErrNoRecord)
mockBuilder.EXPECT().Build(gomock.Any()).Return("", 0, errors.ErrNoRecord)

i := New(mockBuilder, mockClientPool)
resp, err := i.Import(spec.Record{})
Expand All @@ -45,7 +45,7 @@ var _ = Describe("Importer", func() {
})

It("execute failed", func() {
mockBuilder.EXPECT().Build(gomock.Any()).Return("statement", nil)
mockBuilder.EXPECT().Build(gomock.Any()).Return("statement", 1, nil)
mockClientPool.EXPECT().Execute(gomock.Any()).Return(nil, stderrors.New("test error"))

i := New(mockBuilder, mockClientPool)
Expand All @@ -58,7 +58,7 @@ var _ = Describe("Importer", func() {
})

It("execute IsSucceed false", func() {
mockBuilder.EXPECT().Build(gomock.Any()).Return("statement", nil)
mockBuilder.EXPECT().Build(gomock.Any()).Return("statement", 1, nil)
mockClientPool.EXPECT().Execute(gomock.Any()).Times(1).Return(mockResponse, nil)
mockResponse.EXPECT().IsSucceed().Times(1).Return(false)
mockResponse.EXPECT().GetError().Times(1).Return(stderrors.New("status failed"))
Expand All @@ -74,7 +74,7 @@ var _ = Describe("Importer", func() {
})

It("execute successfully", func() {
mockBuilder.EXPECT().Build(gomock.Any()).Times(1).Return("statement", nil)
mockBuilder.EXPECT().Build(gomock.Any()).Times(1).Return("statement", 1, nil)
mockClientPool.EXPECT().Execute(gomock.Any()).Times(1).Return(mockResponse, nil)
mockResponse.EXPECT().IsSucceed().Times(1).Return(true)
mockResponse.EXPECT().GetLatency().Times(1).Return(time.Microsecond * 10)
Expand All @@ -91,7 +91,7 @@ var _ = Describe("Importer", func() {
})

It("execute successfully with Add, Wait and Done", func() {
mockBuilder.EXPECT().Build(gomock.Any()).Times(2).Return("statement", nil)
mockBuilder.EXPECT().Build(gomock.Any()).Times(2).Return("statement", 1, nil)
mockClientPool.EXPECT().Execute(gomock.Any()).Times(2).Return(mockResponse, nil)
mockResponse.EXPECT().IsSucceed().Times(2).Return(true)
mockResponse.EXPECT().GetLatency().Times(2).Return(time.Microsecond * 10)
Expand Down
8 changes: 4 additions & 4 deletions pkg/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ func (m *defaultManager) submitImporterTask(nBytes int, records spec.Records, im
m.onRequestFailed(records)
isFailed = true
// do not return, continue the subsequent importer.
} else {
m.onRequestSucceeded(records, result)
} else if result.RecordNum > 0 {
m.onRequestSucceeded(result)
}
}
}
Expand Down Expand Up @@ -428,8 +428,8 @@ func (m *defaultManager) onRequestFailed(records spec.Records) {
m.stats.RequestFailed(int64(len(records)))
}

func (m *defaultManager) onRequestSucceeded(records spec.Records, result *importer.ImportResp) {
m.stats.RequestSucceeded(int64(len(records)), result.Latency, result.RespTime)
func (m *defaultManager) onRequestSucceeded(result *importer.ImportResp) {
m.stats.RequestSucceeded(int64(result.RecordNum), result.Latency, result.RespTime)
}

func (m *defaultManager) logError(err error, msg string, fields ...logger.Field) {
Expand Down
5 changes: 3 additions & 2 deletions pkg/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ var _ = Describe("Manager", func() {
return nil, stderrors.New("import failed")
}
return &importer.ImportResp{
Latency: 2 * time.Microsecond,
RespTime: 3 * time.Microsecond,
RecordNum: len(records),
Latency: 2 * time.Microsecond,
RespTime: 3 * time.Microsecond,
}, nil
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/spec/base/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ package specbase
type (
// StatementBuilder is the interface to build statement
StatementBuilder interface {
Build(records ...Record) (string, error)
Build(records ...Record) (statement string, nRecord int, err error)
}

StatementBuilderFunc func(records ...Record) (string, error)
StatementBuilderFunc func(records ...Record) (statement string, nRecord int, err error)
)

func (f StatementBuilderFunc) Build(records ...Record) (string, error) {
func (f StatementBuilderFunc) Build(records ...Record) (statement string, nRecord int, err error) {
return f(records...)
}
7 changes: 4 additions & 3 deletions pkg/spec/base/builder_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading