Skip to content
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/field delete #91

Merged
merged 5 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dev.workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install Node&Npm
uses: actions/setup-node@v2
with:
node-version: '14'
node-version: '18'
- name: Checkout code
uses: actions/checkout@v2
- name: Retrieve new version
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/master.workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install Node&Npm
uses: actions/setup-node@v2
with:
node-version: '14'
node-version: '18'
- name: Checkout code
uses: actions/checkout@v2
- name: Retrieve new version
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ It's also possible to delete multiple documents without transaction
fuego delete people Rv7ZfnLQWprdXuulqMdf,Rv7ZfnLQWprdXuulqMde
```

Deleting a specific field of a document, the ```--field, -f``` flag can be used.
```sh
fuego delete people/Rv7ZfnLQWprdXuulqMdf -f age
```
This command will delete the age field from the given doument path.


To update an existing document:

Expand Down
29 changes: 27 additions & 2 deletions delete.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package main

import (
firestore "cloud.google.com/go/firestore"
"context"
"fmt"
"log"

firestore "cloud.google.com/go/firestore"
"github.com/urfave/cli"
"google.golang.org/api/iterator"
"log"
)

func deleteCommandAction(c *cli.Context) error {
Expand All @@ -18,6 +19,11 @@ func deleteCommandAction(c *cli.Context) error {
}

deleteRecursive := c.Bool("recursive")
deleteField := c.String("field")

if deleteRecursive && deleteField != "" {
return cli.NewExitError("recursive delete and field delete can't be combined!", 82)
}

client, err := createClient(credentials)
if err != nil {
Expand All @@ -36,6 +42,8 @@ func deleteCommandAction(c *cli.Context) error {
documentRef = client.Doc(documentPath)
}

defer client.Close()

if deleteRecursive {
deleteBatch := client.Batch()
err = deleteSubCollections(documentRef, client, deleteBatch)
Expand All @@ -49,6 +57,23 @@ func deleteCommandAction(c *cli.Context) error {
}
}

if deleteField != "" {

_, err := documentRef.Update(
context.Background(),
[]firestore.Update{{
Path: deleteField,
Value: firestore.Delete,
},
})

if err != nil {
return cli.NewExitError(fmt.Sprintf("failed to delete field. \n%v", err), 82)
}

return nil
}

res, err := documentRef.Delete(context.Background())
if err != nil {
return cli.NewExitError(fmt.Sprintf("Failed to delete data. \n%v", res), 82)
Expand Down
7 changes: 6 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package main

import (
"fmt"
"github.com/urfave/cli"
"log"
"os"

"github.com/urfave/cli"
)

// Global configuration
Expand Down Expand Up @@ -48,6 +49,10 @@ func main() {
Name: "recursive, r",
Usage: "Recursively delete sub-collections",
},
cli.StringFlag{
Name: "field, f",
Usage: "Delete specific field of document",
},
}

app.Commands = []cli.Command{
Expand Down
81 changes: 56 additions & 25 deletions tests/tests
Original file line number Diff line number Diff line change
Expand Up @@ -350,31 +350,62 @@ testCopyDocumentAndCollection(){
}

testDeleteRecursive(){
# adding new documents with nested sub-collections
id=$(../fuego add ${TEST_COLLECTION} "{\"base\": \"value\"}") || fail "Failed to add document"
subDocId1=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1" "{\"base\": \"sub value1\"}") || fail "Failed to add document"
subSubDocId1=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1" "{\"base\": \"subsub value1\"}")|| fail "Failed to add document"

subDocId2=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection2" "{\"base\": \"sub value2\"}") || fail "Failed to add document"
subSubDocId2=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection2/${subDocId2}/subSubCollection2" "{\"base\": \"subsub value2\"}")|| fail "Failed to add document"
echo ${id} ${subDocId1} ${subSubDocId1} ${subDocId2} ${subSubDocId2}

# delete one collection without recursive flag. To test deletion of missing documents.
../fuego delete "${TEST_COLLECTION}/${id}/subCollection1" ${subDocId1}
assertFalse "Should not have read deleted value" "../fuego get ${TEST_COLLECTION}/${id}/subCollection1 ${subDocId1}"

# check that sub-collection of deleted collection still exists
expectedValue=$(echo "{\"base\": \"subsub value1\"}" | jq .)
result=$(../fuego get "${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1/${subSubDocId1}" | jq .Data)
assertEquals "Should be able to read SubCollection" "${result}" "${expectedValue}"

# call delete again, but with recursive flag.
../fuego delete -r "${TEST_COLLECTION}" ${id}

# check that all documents are deleted, also the missing documents.
assertFalse "Should not have read deleted value2" "../fuego get ${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1 ${subSubDocId1}"
assertFalse "Should not have read deleted value3" "../fuego get ${TEST_COLLECTION}/${id}/subCollection2 ${subDocId2}"
assertFalse "Should not have read deleted value2" "../fuego get ${TEST_COLLECTION}/${id}/subCollection2/${subDocId2}/subSubCollection2 ${subSubDocId2}"
# adding new documents with nested sub-collections
id=$(../fuego add ${TEST_COLLECTION} "{\"base\": \"value\"}") || fail "Failed to add document"
subDocId1=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1" "{\"base\": \"sub value1\"}") || fail "Failed to add document"
subSubDocId1=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1" "{\"base\": \"subsub value1\"}")|| fail "Failed to add document"

subDocId2=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection2" "{\"base\": \"sub value2\"}") || fail "Failed to add document"
subSubDocId2=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection2/${subDocId2}/subSubCollection2" "{\"base\": \"subsub value2\"}")|| fail "Failed to add document"
echo ${id} ${subDocId1} ${subSubDocId1} ${subDocId2} ${subSubDocId2}

# delete one collection without recursive flag. To test deletion of missing documents.
../fuego delete "${TEST_COLLECTION}/${id}/subCollection1" ${subDocId1}
assertFalse "Should not have read deleted value" "../fuego get ${TEST_COLLECTION}/${id}/subCollection1 ${subDocId1}"

# check that sub-collection of deleted collection still exists
expectedValue=$(echo "{\"base\": \"subsub value1\"}" | jq .)
result=$(../fuego get "${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1/${subSubDocId1}" | jq .Data)
assertEquals "Should be able to read SubCollection" "${result}" "${expectedValue}"

# call delete again, but with recursive flag.
../fuego delete -r "${TEST_COLLECTION}" ${id}

# check that all documents are deleted, also the missing documents.
assertFalse "Should not have read deleted value2" "../fuego get ${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subSubCollection1 ${subSubDocId1}"
assertFalse "Should not have read deleted value3" "../fuego get ${TEST_COLLECTION}/${id}/subCollection2 ${subDocId2}"
assertFalse "Should not have read deleted value2" "../fuego get ${TEST_COLLECTION}/${id}/subCollection2/${subDocId2}/subSubCollection2 ${subSubDocId2}"
}

testFieldDelete(){
# adding new documents with sub-collections and two fields
id=$(../fuego add ${TEST_COLLECTION} "{\"base\": \"value\", \"base2\": \"value2\"}") || fail "Failed to add document"
subDocId1=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1" "{\"subbase\": \"sub value1\"}") || fail "Failed to add document"
subDocId2=$(../fuego add "${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}/subCollection2" "{\"sub2base\": \"sub2 value1\"}") || fail "Failed to add document"
echo ${id} ${subDocId1} ${subDocId2}

# check preconditions for first level
result=$(../fuego get ${TEST_COLLECTION}/${id} | jq -c .Data)
expectedValue='{"base":"value","base2":"value2"}'
assertEquals "Preconditions Failed" "${result}" "${expectedValue}"

# delete field from first level
../fuego delete -f "base2" ${TEST_COLLECTION}/${id}
result=$(../fuego get ${TEST_COLLECTION}/${id} | jq -c .Data)
expectedValue='{"base":"value"}'
assertEquals "Failed to delete from First level" "${result}" "${expectedValue}"

# check preconditions for second level
result=$(../fuego get ${TEST_COLLECTION}/${id}/subCollection1/${subDocId1} | jq -c .Data)
expectedValue='{"subbase":"sub value1"}'
assertEquals "Preconditions Failed" "${result}" "${expectedValue}"

# delete field from second level
../fuego delete -f "subbase" ${TEST_COLLECTION}/${id}/subCollection1/${subDocId1}
result=$(../fuego get ${TEST_COLLECTION}/${id}/subCollection1/${subDocId1} | jq -c .Data)
expectedValue='{}'
assertEquals "Failed to delete from First level" "${result}" "${expectedValue}"
}

# Load shUnit2.
. ./shunit2
Loading