fix(search): compose the mediatype:file negation correctly

The file expansion is grouped again so its NOT stays atomic next to other terms (OpenSearch turned 'mediatype:file OR x' into '(NOT dir) AND x'), and the bleve compiler no longer re-keys resolved groups (a negated mediatype group targeted the raw 'mediatype' field and matched everything). Pinned as MEDIATYPE-07..10.
This commit is contained in:
Dominik Schmidt committed 2026-08-31 13:43:19 +02:00
1 parent 9503884472
commit 9e8bb474b4
5 files changed
+19 -19

No files matched your search

@@ -20,6 +20,10 @@ func mediatypeGroup() queryGroup {
{id: 4, query: `mediatype:*jpeg`, want: []string{"photo.jpg"}},
{id: 5, query: `mediatype:image`, want: []string{"photo.jpg"}},
{id: 6, query: `mediatype:folder`, want: []string{"albums", "drafts"}},
{id: 7, query: `mediatype:file`, want: []string{"notes.md", "photo.jpg"}},
{id: 8, query: `NOT mediatype:file`, want: []string{"albums", "drafts"}},
{id: 9, query: `mediatype:file OR mediatype:image`, want: []string{"notes.md", "photo.jpg"}},
{id: 10, query: `NOT mediatype:(image OR folder)`, want: []string{"notes.md"}},
},
}
}
+1 -13
View File
@@ -269,10 +269,7 @@ func walk(offset int, nodes []ast.Node) (bleveQuery.Query, int, error) {
func nextNode(offset int, nodes []ast.Node) (bleveQuery.Query, int, error) {
if n, ok := nodes[offset].(*ast.GroupNode); ok {
if n.Key != "" {
n = normalizeGroupingProperty(n)
}
// keys are resolved and group keys propagated by normalize
gq, _, err := walk(0, n.Nodes)
if err != nil {
return nil, 0, err
@@ -359,12 +356,3 @@ func numberRange(field string, operator *ast.OperatorNode, value float64) bleveQ
return q
}
func normalizeGroupingProperty(group *ast.GroupNode) *ast.GroupNode {
for _, n := range group.Nodes {
if onode, ok := n.(*ast.StringNode); ok {
onode.Key = group.Key
}
}
return group
}
@@ -23,9 +23,13 @@ func Expand(key, value string) []ast.Node {
value = strings.ToLower(value)
switch value {
case "file":
// grouped so the negation stays atomic when it composes with other
// terms (mediatype:file OR ...)
return []ast.Node{
&ast.OperatorNode{Value: kql.BoolNOT},
&ast.StringNode{Key: field, Value: "httpd/unix-directory"},
&ast.GroupNode{Nodes: []ast.Node{
&ast.OperatorNode{Value: kql.BoolNOT},
&ast.StringNode{Key: field, Value: "httpd/unix-directory"},
}},
}
case "folder":
return term("httpd/unix-directory")
@@ -56,8 +56,10 @@ var _ = Describe("Expand", func() {
It("expands file to not-a-folder", func() {
Expect(mimetype.Expand("mediatype", "file")).To(Equal([]ast.Node{
&ast.OperatorNode{Value: "NOT"},
&ast.StringNode{Key: "MimeType", Value: "httpd/unix-directory"},
&ast.GroupNode{Nodes: []ast.Node{
&ast.OperatorNode{Value: "NOT"},
&ast.StringNode{Key: "MimeType", Value: "httpd/unix-directory"},
}},
}))
})
+4 -2
View File
@@ -73,8 +73,10 @@ var _ = Describe("Normalize", func() {
&ast.OperatorNode{Value: "AND"},
&ast.StringNode{Key: "photo.cameraMake", Value: "canon", CaseInsensitive: true},
&ast.OperatorNode{Value: "AND"},
&ast.OperatorNode{Value: "NOT"},
&ast.StringNode{Key: "MimeType", Value: "httpd/unix-directory"},
&ast.GroupNode{Nodes: []ast.Node{
&ast.OperatorNode{Value: "NOT"},
&ast.StringNode{Key: "MimeType", Value: "httpd/unix-directory"},
}},
&ast.OperatorNode{Value: "AND"},
&ast.NumberNode{Key: "Size", Value: 100},
}))