-
Notifications
You must be signed in to change notification settings - Fork 53
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: JSON type filter #3122
feat: JSON type filter #3122
Changes from all commits
75b75c5
6217bff
27a4b12
60c42d8
fdfebac
ab41829
48cddd8
1384e30
1b6f3fa
cd4fe32
3a4e006
2975ef9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
var ( | ||
_ connor.FilterKey = (*PropertyIndex)(nil) | ||
_ connor.FilterKey = (*Operator)(nil) | ||
_ connor.FilterKey = (*ObjectProperty)(nil) | ||
) | ||
|
||
// PropertyIndex is a FilterKey that represents a property in a document. | ||
|
@@ -71,6 +72,34 @@ | |
return false | ||
} | ||
|
||
// ObjectProperty is a FilterKey that represents a property in an object. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. todo: Similar to another comment, I think it is important to document why both this and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be more clear now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good, thanks Keenan |
||
// | ||
// This is used to target properties of an object when the fields | ||
// are not explicitly mapped, such as with JSON. | ||
type ObjectProperty struct { | ||
// The name of the property on object. | ||
Name string | ||
} | ||
|
||
func (k *ObjectProperty) GetProp(data any) any { | ||
if data == nil { | ||
return nil | ||
} | ||
object := data.(map[string]any) | ||
return object[k.Name] | ||
} | ||
|
||
func (k *ObjectProperty) GetOperatorOrDefault(defaultOp string) string { | ||
return defaultOp | ||
} | ||
|
||
func (k *ObjectProperty) Equal(other connor.FilterKey) bool { | ||
if otherKey, isOk := other.(*ObjectProperty); isOk && *k == *otherKey { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
// Filter represents a series of conditions that may reduce the number of | ||
// records that a request returns. | ||
type Filter struct { | ||
|
@@ -144,6 +173,14 @@ | |
default: | ||
outmap[keyType.Operation] = v | ||
} | ||
|
||
case *ObjectProperty: | ||
switch subObj := v.(type) { | ||
case map[connor.FilterKey]any: | ||
outmap[keyType.Name] = filterObjectToMap(mapping, subObj) | ||
case nil: | ||
outmap[keyType.Name] = nil | ||
} | ||
} | ||
} | ||
return outmap | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1202,43 +1202,18 @@ | |
} | ||
|
||
// generate basic filter operator blocks | ||
// @todo: Extract object field loop into its own utility func | ||
for f, field := range obj.Fields() { | ||
if _, ok := request.ReservedFields[f]; ok && f != request.DocIDFieldName { | ||
_, ok := request.ReservedFields[f] | ||
if ok && f != request.DocIDFieldName { | ||
continue | ||
} | ||
// scalars (leafs) | ||
if gql.IsLeafType(field.Type) { | ||
var operatorName string | ||
if list, isList := field.Type.(*gql.List); isList { | ||
if notNull, isNotNull := list.OfType.(*gql.NonNull); isNotNull { | ||
operatorName = "NotNull" + notNull.OfType.Name() + "ListOperatorBlock" | ||
} else { | ||
operatorName = list.OfType.Name() + "ListOperatorBlock" | ||
} | ||
} else { | ||
operatorName = field.Type.Name() + "OperatorBlock" | ||
} | ||
operatorType, isFilterable := g.manager.schema.TypeMap()[operatorName] | ||
if !isFilterable { | ||
continue | ||
} | ||
fields[field.Name] = &gql.InputObjectFieldConfig{ | ||
Type: operatorType, | ||
} | ||
} else { // objects (relations) | ||
fieldType := field.Type | ||
if l, isList := field.Type.(*gql.List); isList { | ||
// We want the FilterArg for the object, not the list of objects. | ||
fieldType = l.OfType | ||
} | ||
filterType, isFilterable := g.manager.schema.TypeMap()[genTypeName(fieldType, filterInputNameSuffix)] | ||
if !isFilterable { | ||
filterType = &gql.InputObjectField{} | ||
} | ||
fields[field.Name] = &gql.InputObjectFieldConfig{ | ||
Type: filterType, | ||
} | ||
operatorName := genFilterOperatorName(field.Type) | ||
filterType, isFilterable := g.manager.schema.TypeMap()[operatorName] | ||
if !isFilterable { | ||
continue | ||
} | ||
fields[field.Name] = &gql.InputObjectFieldConfig{ | ||
Type: filterType, | ||
} | ||
} | ||
|
||
|
@@ -1408,6 +1383,35 @@ | |
list.OfType == gql.Float | ||
} | ||
|
||
func genFilterOperatorName(fieldType gql.Type) string { | ||
list, isList := fieldType.(*gql.List) | ||
if isList { | ||
fieldType = list.OfType | ||
} | ||
if !gql.IsLeafType(fieldType) { | ||
return genTypeName(fieldType, filterInputNameSuffix) | ||
} | ||
notNull, isNotNull := fieldType.(*gql.NonNull) | ||
if isNotNull { | ||
fieldType = notNull.OfType | ||
} | ||
switch { | ||
case fieldType.Name() == "JSON": | ||
return fieldType.Name() | ||
|
||
case isList && isNotNull: | ||
// todo: There's a potential to have a name clash | ||
// https://github.com/sourcenetwork/defradb/issues/3123 | ||
return "NotNull" + fieldType.Name() + "ListOperatorBlock" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thought: It looks like we have a name clash here - I've created a ticket - would you mind adding a todo comment linking to the ticket, and then amend the issue-description to note taht there is a code-todo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks :) |
||
|
||
case isList: | ||
return fieldType.Name() + "ListOperatorBlock" | ||
|
||
default: | ||
return fieldType.Name() + "OperatorBlock" | ||
} | ||
} | ||
|
||
/* Example | ||
|
||
typeDefs := ` ... ` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
praise: This comment is very helpful - thanks Keenan