Skip to content

Commit

Permalink
Filter reworked
Browse files Browse the repository at this point in the history
  • Loading branch information
jomei committed Aug 8, 2021
1 parent 9e5dc58 commit cb95dc1
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 26 deletions.
29 changes: 25 additions & 4 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,31 @@ type DatabaseListResponse struct {
}

type DatabaseQueryRequest struct {
Filter Filter `json:"filter,omitempty"`
Sorts []SortObject `json:"sorts"`
StartCursor Cursor `json:"start_cursor,omitempty"`
PageSize int `json:"page_size,omitempty"`
PropertyFilter *PropertyFilter
CompoundFilter *CompoundFilter
Sorts []SortObject `json:"sorts,omitempty"`
StartCursor Cursor `json:"start_cursor,omitempty"`
PageSize int `json:"page_size,omitempty"`
}

func (qr *DatabaseQueryRequest) MarshalJSON() ([]byte, error) {
var filter interface{}
if qr.PropertyFilter != nil {
filter = qr.PropertyFilter
} else {
filter = qr.CompoundFilter
}
return json.Marshal(struct {
Sorts []SortObject `json:"sorts,omitempty"`
StartCursor Cursor `json:"start_cursor,omitempty"`
PageSize int `json:"page_size,omitempty"`
Filter interface{} `json:"filter"`
}{
Sorts: qr.Sorts,
StartCursor: qr.StartCursor,
PageSize: qr.PageSize,
Filter: filter,
})
}

type DatabaseQueryResponse struct {
Expand Down
99 changes: 96 additions & 3 deletions database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ func TestDatabaseClient(t *testing.T) {
filePath: "testdata/database_query.json",
statusCode: http.StatusOK,
request: &notionapi.DatabaseQueryRequest{
Filter: &notionapi.PropertyFilter{
PropertyFilter: &notionapi.PropertyFilter{
Property: "Name",
Text: map[notionapi.Condition]string{
notionapi.ConditionContains: "Hel",
Text: &notionapi.TextFilterCondition{
Contains: "Hel",
},
},
},
Expand Down Expand Up @@ -213,3 +213,96 @@ func TestDatabaseClient(t *testing.T) {
}
})
}

func TestDatabaseQueryRequest_MarshalJSON(t *testing.T) {
timeObj, err := time.Parse(time.RFC3339, "2021-05-10T02:43:42Z")
if err != nil {
t.Error(err)
return
}
dateObj := notionapi.Date(timeObj)
tests := []struct {
name string
req *notionapi.DatabaseQueryRequest
want []byte
wantErr bool
}{
{
name: "with property filter without sort",
req: &notionapi.DatabaseQueryRequest{
PropertyFilter: &notionapi.PropertyFilter{
Property: "Status",
Select: &notionapi.SelectFilterCondition{
Equals: "Reading",
},
},
},
want: []byte(`{"filter":{"property":"Status","select":{"equals":"Reading"}}}`),
},
{
name: "with property filter with sort",
req: &notionapi.DatabaseQueryRequest{
PropertyFilter: &notionapi.PropertyFilter{
Property: "Status",
Select: &notionapi.SelectFilterCondition{
Equals: "Reading",
},
},
Sorts: []notionapi.SortObject{
{
Property: "Score /5",
Direction: notionapi.SortOrderASC,
},
},
},
want: []byte(`{"sorts":[{"property":"Score /5","direction":"ascending"}],"filter":{"property":"Status","select":{"equals":"Reading"}}}`),
},
{
name: "compound filter",
req: &notionapi.DatabaseQueryRequest{
CompoundFilter: &notionapi.CompoundFilter{
notionapi.FilterOperatorOR: []notionapi.PropertyFilter{
{
Property: "Status",
Select: &notionapi.SelectFilterCondition{
Equals: "Reading",
},
},
{
Property: "Publisher",
Select: &notionapi.SelectFilterCondition{
Equals: "NYT",
},
},
},
},
},
want: []byte(`{"filter":{"or":[{"property":"Status","select":{"equals":"Reading"}},{"property":"Publisher","select":{"equals":"NYT"}}]}}`),
},
{
name: "date filter",
req: &notionapi.DatabaseQueryRequest{
PropertyFilter: &notionapi.PropertyFilter{
Property: "created_at",
Date: &notionapi.DateFilterCondition{
Equals: &dateObj,
PastWeek: &struct{}{},
},
},
},
want: []byte(`{"filter":{"property":"created_at","date":{"equals":"2021-05-10T02:43:42Z","past_week":{}}}}`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.req.MarshalJSON()
if (err != nil) != tt.wantErr {
t.Errorf("MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("MarshalJSON() got = %s, want %s", got, tt.want)
}
})
}
}
111 changes: 95 additions & 16 deletions filter.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,104 @@
package notionapi

import "time"

type FilterOperator string

type Filter interface{}

type CompoundFilter map[FilterOperator]Filter
type CompoundFilter map[FilterOperator][]PropertyFilter

type Condition string

type PropertyFilter struct {
Property PropertyType `json:"property"`
Text map[Condition]string `json:"text,omitempty"`
Number map[Condition]float64 `json:"number,omitempty"`
Checkbox map[Condition]bool `json:"checkbox,omitempty"`
Select map[Condition]interface{} `json:"select,omitempty"`
MultiSelect map[Condition]interface{} `json:"multi_select,omitempty"`
Date map[Condition]time.Time `json:"date,omitempty"`
People map[Condition]interface{} `json:"people,omitempty"`
Files map[Condition]bool `json:"files,omitempty"`
Relation map[Condition]interface{} `json:"relation,omitempty"`
Formula map[PropertyType]PropertyFilter `json:"formula,omitempty"`
Property string `json:"property"`
Text *TextFilterCondition `json:"text,omitempty"`
Number *NumberFilterCondition `json:"number,omitempty"`
Checkbox *CheckboxFilterCondition `json:"checkbox,omitempty"`
Select *SelectFilterCondition `json:"select,omitempty"`
MultiSelect *MultiSelectFilterCondition `json:"multi_select,omitempty"`
Date *DateFilterCondition `json:"date,omitempty"`
People *PeopleFilterCondition `json:"people,omitempty"`
Files *FilesFilterCondition `json:"files,omitempty"`
Relation *RelationFilterCondition `json:"relation,omitempty"`
Formula *FormulaFilterCondition `json:"formula,omitempty"`
}

type TextFilterCondition struct {
Equals string `json:"equals,omitempty"`
DoesNotEqual string `json:"does_not_equal,omitempty"`
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
StartsWith string `json:"starts_with,omitempty"`
EndsWith string `json:"ends_with,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type NumberFilterCondition struct {
Equals float64 `json:"equals,omitempty"`
DoesNotEqual float64 `json:"does_not_equal,omitempty"`
GreaterThan float64 `json:"greater_than,omitempty"`
LessThan float64 `json:"less_than,omitempty"`
GreaterThanOrEqualTo float64 `json:"greater_than_or_equal_to"`
LessThanOrEqualTo float64 `json:"less_than_or_equal_to"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type CheckboxFilterCondition struct {
Equals bool `json:"equals,omitempty"`
DoesNotEqual bool `json:"does_not_equal,omitempty"`
}

type SelectFilterCondition struct {
Equals string `json:"equals,omitempty"`
DoesNotEqual string `json:"does_not_equal,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type MultiSelectFilterCondition struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type DateFilterCondition struct {
Equals *Date `json:"equals,omitempty"`
Before *Date `json:"before,omitempty"`
After *Date `json:"after,omitempty"`
OnOrBefore *Date `json:"on_or_before,omitempty"`
OnOrAfter *Date `json:"on_or_after,omitempty"`
PastWeek *struct{} `json:"past_week,omitempty"`
PastMonth *struct{} `json:"past_month,omitempty"`
PastYear *struct{} `json:"past_year,omitempty"`
NextWeek *struct{} `json:"next_week,omitempty"`
NextMonth *struct{} `json:"next_month,omitempty"`
NextYear *struct{} `json:"next_year,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type PeopleFilterCondition struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type FilesFilterCondition struct {
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type RelationFilterCondition struct {
Contains string `json:"contains,omitempty"`
DoesNotContain string `json:"does_not_contain,omitempty"`
IsEmpty bool `json:"is_empty,omitempty"`
IsNotEmpty bool `json:"is_not_empty,omitempty"`
}

type FormulaFilterCondition struct {
Text *TextFilterCondition `json:"text,omitempty"`
Checkbox *CheckboxFilterCondition `json:"checkbox,omitempty"`
Number *NumberFilterCondition `json:"number,omitempty"`
Date *DateFilterCondition `json:"date,omitempty"`
}
12 changes: 12 additions & 0 deletions object.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package notionapi

import "time"

type ObjectType string

func (ot ObjectType) String() string {
Expand Down Expand Up @@ -66,3 +68,13 @@ type Cursor string
func (c Cursor) String() string {
return string(c)
}

type Date time.Time

func (d *Date) String() string {
return time.Time(*d).Format(time.RFC3339)
}

func (d *Date) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
2 changes: 1 addition & 1 deletion search.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (sc *SearchClient) Do(ctx context.Context, request *SearchRequest) (*Search
type SearchRequest struct {
Query string `json:"query,omitempty"`
Sort *SortObject `json:"sort,omitempty"`
Filter Filter `json:"filter,omitempty"`
Filter interface{} `json:"filter,omitempty"`
StartCursor Cursor `json:"start_cursor,omitempty"`
PageSize int `json:"page_size"`
}
Expand Down
4 changes: 2 additions & 2 deletions sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ type TimestampType string

type SortObject struct {
Property string `json:"property,omitempty"`
Timestamp TimestampType `json:"timestamp"`
Direction SortOrder `json:"direction"`
Timestamp TimestampType `json:"timestamp,omitempty"`
Direction SortOrder `json:"direction,omitempty"`
}

0 comments on commit cb95dc1

Please sign in to comment.