Skip to content

Commit

Permalink
Fix small issues after rewrite (#380)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekSi committed Mar 21, 2022
1 parent 1cae572 commit b0804b4
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 82 deletions.
115 changes: 60 additions & 55 deletions internal/handlers/common/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,63 +49,13 @@ func FilterDocument(doc, filter *types.Document) (bool, error) {

// filterDocumentPair handles a single filter element key/value pair {filterKey: filterValue}.
func filterDocumentPair(doc *types.Document, filterKey string, filterValue any) (bool, error) {
// {$operator: [expr1, expr2, ...]}
if strings.HasPrefix(filterKey, "$") {
exprs, ok := filterValue.(*types.Array)
if !ok {
msg := fmt.Sprintf(
`unknown top level operator: %s. `+
`If you have a field name that starts with a '$' symbol, consider using $getField or $setField.`,
filterKey,
)
return false, NewErrorMsg(ErrBadValue, msg)
}

switch filterKey {
case "$and":
// {$and: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if !matches {
return false, nil
}
}
return true, nil

case "$or":
// {$or: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if matches {
return true, nil
}
}
return false, nil

case "$nor":
// {$nor: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if matches {
return false, nil
}
}
return true, nil
// {$operator: [expr1, expr2, ...]}
exprs, err := AssertType[*types.Array](filterValue)
if err != nil {
return false, err
}

panic(fmt.Sprintf("filterDocumentPair: %q %v", filterKey, filterValue))
return filterLala(doc, filterKey, exprs)
}

docValue, err := doc.Get(filterKey)
Expand All @@ -132,6 +82,61 @@ func filterDocumentPair(doc *types.Document, filterKey string, filterValue any)
}
}

// filterLala handles {$operator: [expr1, expr2, ...]} filter.
func filterLala(doc *types.Document, operator string, exprs *types.Array) (bool, error) {
switch operator {
case "$and":
// {$and: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if !matches {
return false, nil
}
}
return true, nil

case "$or":
// {$or: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if matches {
return true, nil
}
}
return false, nil

case "$nor":
// {$nor: [{expr1}, {expr2}, ...]}
for i := 0; i < exprs.Len(); i++ {
expr := must.NotFail(exprs.Get(i)).(*types.Document)
matches, err := FilterDocument(doc, expr)
if err != nil {
panic(err)
}
if matches {
return false, nil
}
}
return true, nil

default:
msg := fmt.Sprintf(
`unknown top level operator: %s. `+
`If you have a field name that starts with a '$' symbol, consider using $getField or $setField.`,
operator,
)
return false, NewErrorMsg(ErrBadValue, msg)
}
}

// filterFieldExpr handles {field: {expr}} filter.
func filterFieldExpr(fieldValue any, expr *types.Document) (bool, error) {
for _, exprKey := range expr.Keys() {
Expand Down
2 changes: 1 addition & 1 deletion internal/handlers/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ func TestFind(t *testing.T) {
req: must.NotFail(types.NewDocument(
"find", "values",
"filter", must.NotFail(types.NewDocument(
"$size", int32(2),
"$size", types.MustNewArray(int32(2)),
)),
)),
err: common.NewErrorMsg(
Expand Down
27 changes: 3 additions & 24 deletions internal/handlers/jsonb1/msg_count.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import (
"github.com/FerretDB/FerretDB/internal/wire"
)

// MsgFindOrCount finds documents in a collection or view and returns a cursor to the selected documents
// or count the number of documents that matches the query filter.
// MsgCount counts the number of documents that matches the query filter.
func (s *storage) MsgCount(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) {
document, err := msg.Document()
if err != nil {
Expand All @@ -33,29 +32,15 @@ func (s *storage) MsgCount(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, e

unimplementedFields := []string{
"skip",
"returnKey",
"showRecordId",
"tailable",
"oplogReplay",
"noCursorTimeout",
"awaitData",
"allowPartialResults",
"collation",
"allowDiskUse",
"let",
}
if err := common.Unimplemented(document, unimplementedFields...); err != nil {
return nil, err
}
ignoredFields := []string{
"hint",
"batchSize",
"singleBatch",
"comment",
"maxTimeMS",
"readConcern",
"max",
"min",
"comment",
}
common.Ignored(document, s.l, ignoredFields...)

Expand All @@ -69,14 +54,11 @@ func (s *storage) MsgCount(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, e
return nil, err
}

var filter, sort *types.Document
var filter *types.Document
var limit int32
if filter, err = common.GetOptionalParam(document, "query", filter); err != nil {
return nil, err
}
if sort, err = common.GetOptionalParam(document, "sort", sort); err != nil {
return nil, err
}
if limit, err = common.GetOptionalParam(document, "limit", limit); err != nil {
return nil, err
}
Expand All @@ -100,9 +82,6 @@ func (s *storage) MsgCount(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, e
resDocs = append(resDocs, doc)
}

if err = common.SortDocuments(resDocs, sort); err != nil {
return nil, err
}
if resDocs, err = common.LimitDocuments(resDocs, limit); err != nil {
return nil, err
}
Expand Down
3 changes: 1 addition & 2 deletions internal/handlers/jsonb1/msg_find.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import (
"github.com/FerretDB/FerretDB/internal/wire"
)

// MsgFindOrCount finds documents in a collection or view and returns a cursor to the selected documents
// or count the number of documents that matches the query filter.
// MsgFind finds documents in a collection or view and returns a cursor to the selected documents.
func (s *storage) MsgFind(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) {
document, err := msg.Document()
if err != nil {
Expand Down

0 comments on commit b0804b4

Please sign in to comment.