Skip to content

Commit

Permalink
feat: Add ability to delete multiple documents, using multiple ids (#196
Browse files Browse the repository at this point in the history
)

### ISSUE:

Resolves #164
Resolves #165

### DESCRIPTION:

Adds the ability to delete multiple documents, using multiple ids.

We can now delete multiple documents using multiple dockeys (i.e. ids).

For example:
```
mutation {
    delete_user(ids: ["bae-3a1a496e-24eb-5ae3-9c17-524c146a393e" , "bae-6a6482a8-24e1-5c73-a237-ca569e41507d"]) {
        KeyOfDeletedDocument: _key
    }
}
    
```

Gives this on successful deletion of all documents:
```
{
  "data": [
    {
      "KeyOfDeletedDocument": "bae-3a1a496e-24eb-5ae3-9c17-524c146a393e"
    },
    {
      "KeyOfDeletedDocument": "bae-6a6482a8-24e1-5c73-a237-ca569e41507d"
    }
  ]
}
```


### COMMITS:

* feat: Add implementation for deleting multiple documents.

* test: Add tests for the multiple document deletion using multiple keys.

* refactor: Split tests into seperate files for the deletion mutuation
command.

* fix: suppress linter error.
  • Loading branch information
shahzadlone authored Feb 15, 2022
1 parent cdaad72 commit 8ffd2b5
Show file tree
Hide file tree
Showing 5 changed files with 407 additions and 217 deletions.
195 changes: 53 additions & 142 deletions db/collection_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,59 @@ func (c *Collection) DeleteWithKey(ctx context.Context, key key.DocKey, opts ...
return res, c.commitImplicitTxn(ctx, txn)
}

// DeleteWithKeys is the same as DeleteWithKey but accepts multiple keys as a slice.
func (c *Collection) DeleteWithKeys(ctx context.Context, keys []key.DocKey, opts ...client.DeleteOpt) (*client.DeleteResult, error) {

txn, err := c.getTxn(ctx, false)
if err != nil {
return nil, err
}

defer c.discardImplicitTxn(ctx, txn)

res, err := c.deleteWithKeys(ctx, txn, keys, opts...)
if err != nil {
return nil, err
}

return res, c.commitImplicitTxn(ctx, txn)
}

func (c *Collection) deleteWithKeys(ctx context.Context, txn core.Txn, keys []key.DocKey, opts ...client.DeleteOpt) (*client.DeleteResult, error) {

keysDeleted := []string{}

for _, key := range keys {

// Check this docKey actually exists.
found, err := c.exists(ctx, txn, key)

if err != nil {
return nil, err
}
if !found {
return nil, ErrDocumentNotFound
}

// Apply the function that will perform the full deletion of this document.
err = c.applyFullDelete(ctx, txn, key)
if err != nil {
return nil, err
}

// Add this deleted key to our list.
keysDeleted = append(keysDeleted, key.String())
}

// Upon successfull deletion, record a summary.
results := &client.DeleteResult{
Count: int64(len(keysDeleted)),
DocKeys: keysDeleted,
}

return results, nil
}

func (c *Collection) deleteWithKey(ctx context.Context, txn core.Txn, key key.DocKey, opts ...client.DeleteOpt) (*client.DeleteResult, error) {
// Check the docKey we have been given to delete with actually has a corresponding
// document (i.e. document actually exists in the collection).
Expand Down Expand Up @@ -274,163 +327,21 @@ func (d dagDeleter) delete(
// =================================== UNIMPLEMENTED ===================================

// DeleteWithFilter deletes using a filter to target documents for delete.
// An deleter value is provided, which could be a string Patch, string Merge Patch
// or a parsed Patch, or parsed Merge Patch.
func (c *Collection) DeleteWithFilter(ctx context.Context, filter interface{}, opts ...client.DeleteOpt) (*client.DeleteResult, error) {
// txn, err := c.getTxn(ctx, false)
// if err != nil {
// return nil, err
// }
// defer c.discardImplicitTxn(ctx, txn)
// res, err := c.deleteWithFilter(ctx, txn, filter, deleter, opts...)
// if err != nil {
// return nil, err
// }
// return res, c.commitImplicitTxn(ctx, txn)

return nil, nil
}

// DeleteWithKeys is the same as DeleteWithKey but accepts multiple keys as a slice.
// An deleter value is provided, which could be a string Patch, string Merge Patch
// or a parsed Patch, or parsed Merge Patch.
func (c *Collection) DeleteWithKeys(ctx context.Context, keys []key.DocKey, opts ...client.DeleteOpt) (*client.DeleteResult, error) {
// txn, err := c.getTxn(ctx, false)
// if err != nil {
// return nil, err
// }
// defer c.discardImplicitTxn(ctx, txn)
// res, err := c.deleteWithKeys(ctx, txn, keys, deleter, opts...)
// if err != nil {
// return nil, err
// }
// return res, c.commitImplicitTxn(ctx, txn)

return nil, nil
}

// DeleteWithDoc deletes targeting the supplied document.
// An deleter value is provided, which could be a string Patch, string Merge Patch
// or a parsed Patch, or parsed Merge Patch.
func (c *Collection) DeleteWithDoc(doc *document.SimpleDocument, opts ...client.DeleteOpt) error {
return nil
}

// DeleteWithDocs deletes all the supplied documents in the slice.
// An deleter value is provided, which could be a string Patch, string Merge Patch
// or a parsed Patch, or parsed Merge Patch.
func (c *Collection) DeleteWithDocs(docs []*document.SimpleDocument, opts ...client.DeleteOpt) error {
return nil
}

//nolint:unused
func (c *Collection) deleteWithKeys(ctx context.Context, txn core.Txn, keys []key.DocKey, opts ...client.DeleteOpt) (*client.DeleteResult, error) {
// fmt.Println("updating keys:", keys)
// patch, err := parseDeleter(deleter)
// if err != nil {
// return nil, err
// }
//
// isPatch := false
// switch patch.(type) {
// case []map[string]interface{}:
// isPatch = true
// case map[string]interface{}:
// isPatch = false
// default:
// return nil, ErrInvalidDeleter
// }
//
// results := &client.DeleteResult{
// DocKeys: make([]string, len(keys)),
// }
// for i, key := range keys {
// doc, err := c.Get(ctx, key)
// if err != nil {
// fmt.Println("error getting key to delete:", key)
// return nil, err
// }
// v, err := doc.ToMap()
// if err != nil {
// return nil, err
// }
//
// if isPatch {
// // todo
// } else {
// err = c.applyMerge(ctx, txn, v, patch.(map[string]interface{}))
// }
// if err != nil {
// return nil, nil
// }
//
// results.DocKeys[i] = key.String()
// results.Count++
// }
// return results, nil

return nil, nil
}

//nolint:unused
func (c *Collection) deleteWithFilter(ctx context.Context, txn core.Txn, filter interface{}, opts ...client.DeleteOpt) (*client.DeleteResult, error) {
// patch, err := parseDeleter(deleter)
// if err != nil {
// return nil, err
// }

// isPatch := false
// isMerge := false
// switch patch.(type) {
// case []map[string]interface{}:
// isPatch = true
// case map[string]interface{}:
// isMerge = true
// default:
// return nil, ErrInvalidDeleter
// }

// // scan through docs with filter
// query, err := c.makeSelectionQuery(ctx, txn, filter, opts...)
// if err != nil {
// return nil, err
// }
// if err := query.Start(); err != nil {
// return nil, err
// }

// results := &client.DeleteResult{
// DocKeys: make([]string, 0),
// }

// // loop while we still have results from the filter query
// for {
// next, err := query.Next()
// if err != nil {
// return nil, err
// }
// // if theres no more records from the query, jump out of the loop
// if !next {
// break
// }

// // Get the document, and apply the patch
// doc := query.Values()
// if isPatch {
// err = c.applyPatch(txn, doc, patch.([]map[string]interface{}))
// } else if isMerge { // else is fine here
// err = c.applyMerge(ctx, txn, doc, patch.(map[string]interface{}))
// }
// if err != nil {
// return nil, err
// }

// // add successful deleted doc to results
// results.DocKeys = append(results.DocKeys, doc["_key"].(string))
// results.Count++
// }

// return results, nil

return nil, nil
}
14 changes: 0 additions & 14 deletions db/collection_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,6 @@ var (
ErrInvalidMergeValueType = errors.New("The type of value in the merge patch doesn't match the schema")
)

func (c *Collection) Create2(doc *document.SimpleDocument, opts ...CreateOpt) error {

return nil
}

// Update2 updates the given doc. It will scan through the field/value pairs
// and find those marked for update, and apply the appropriate update.
// Update only works on root level field/value pairs. So not foreign or related
// types can be updated. If you wish to update sub types, use UpdateWith, and supply
// an update payload in the form of a Patch or a Merge Patch.
func (c *Collection) Update2(doc *document.SimpleDocument, opts ...client.UpdateOpt) error {
return nil
}

// UpdateWith updates a target document using the given updater type. Target
// can be a Filter statement, a single docKey, a single document,
// an array of docKeys, or an array of documents.
Expand Down
Loading

0 comments on commit 8ffd2b5

Please sign in to comment.