Using Fetch Requests to Update a JSON Database Without Creating Duplicate Database Entries
Tags: javascript, beginners
Published: 2023-10-01 20:31:44

Hello!  In this blog, we will work through a process of checking whether information already exists in a JSON database and, if it doesn't, adding the information to the database.

### Starting Conditions

As an example, we will use a JSON database containing basic information about pets.  Each database entry includes the pet's name, age, and what kind of animal it is.  When a user provides information about a pet, our task is to add the pet to the database.  However, we do not want to create duplicate database entries, so we only want to add the user's input to the database if it does not already exist somewhere in the database.  We start with the following database of pets:

```
{
"pets": [
    {
    "id": 1,
    "name": "Teddy",
    "animal": "dog",
    "age": 5
    },
    {
    "id": 2,
    "name": "Biscuit",
    "animal": "cat",
    "age": 8
    },
    {
    "id": 3,
    "name": "Bubbles",
    "animal": "goldfish",
    "age": 1
    }
]
}
```

The pet information from the user is provided in the following object:

```
let petInput = {
    name: "Scout",
    animal: "dog",
    age: "3"
}
```

### Checking and Updating the Database

#### Retrieving Database Information
In order to compare the user's input with the objects that already exist in the database, we first need to obtain the current database information.  We do this by using fetch() to send a GET request to the JSON database:

```
function getDatabaseInfo(petInput) {
    fetch('http://localhost:3000/pets')
    .then(response => response.json())
    .then(databaseInfo => databaseCheckFunction(databaseInfo, petInput))
}
getDatabaseInfo(petInput)
```

This function, getDatabaseInfo, is being used to start a chain of synchronous functions.  Therefore, the user's input, petInput, is provided as an argument so that it can be passed as an argument as callback functions are invoked.

If you want to review the use of the fetch method and how to handle response received from the database, you can visit this site: https://javascript.info/fetch

#### Searching for Matching Database Entries
Now that we have an array of the current database objects, we can iterate through the array, searching for entries that match the user's input.  For instance, we can use the find() method to search for objects with matching pet names:

```
function databaseCheckFunction(databaseInfo, petInput) {
    let searchedItem = databaseInfo.find(databaseEntry => {
        if (databaseEntry.name == petInput.name) {
            return true}
        })
    if (searchedItem == undefined) {
        addNewPetToDatabase(petInput)
    } else {
        console.log('This pet name already exists in the database')
    }
}
```

.find() will return the matching database entry if a match is found.  If a matching entry is not found, it will return undefined.  We want to add the new pet to the database only if a matching entry is not found, i.e. if .find() returns undefined.  

For more information about using .find(), see the documentation here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

#### Adding New Pet to the Database
If no matching name was found in the database, the following function, addNewPetToDatabase, will be invoked.  This function uses fetch() to send a POST request to add the new pet to database:

```
function addNewPetToDatabase(petInput) {
    fetch('http://localhost:3000/pets', {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        },
        body: JSON.stringify(petInput)
    })
    .then(response => response.json())
    .then(newDatabaseEntry => console.log(newDatabaseEntry))
}
```

After the POST request, we can console log the response to confirm that the pet was successfully added to the database and see the database id number assigned to the pet.

#### Updating Existing Database Entries
In addition to adding a new pet to the database if a matching object value is not found, we can use the same method to update a database entry if a matching object is found.  Instead of having our databaseCheckFunction console log a message if a matching pet name is found, we can pass the petInput object to a function that will use a PATCH or PUT request to update the database:

```
function databaseCheckFunction(databaseInfo, petInput) {
    let searchedItem = databaseInfo.find(databaseEntry => {
        if (databaseEntry.name == petInput.name) {
            return true}
        })
    // .find() will return the matching entry if a match is found.  Otherwise, it will return undefined.  We want to add the new pet to the database if a matching entry is not returned.
    if (searchedItem == undefined) {
        addNewPetToDatabase(petInput)
    } else {
        updatePetInDatabase(petInput)
    }
}
```

In this example, we will use a PUT request to overwrite an existing database entry with the petInput information:

```
function updatePetInDatabase(foundItem, petInput) {
    fetch('http://localhost:3000/pets/'+foundItem.id, {
        method: "PUT",
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        },
        body: JSON.stringify(petInput)
    })
    .then(response => response.json())
    .then(updatedDatabaseEntry => console.log(updatedDatabaseEntry))
}
```

The following blog discusses the difference between PATCH and PUT requests: https://medium.com/@9cv9official/what-are-get-post-put-patch-delete-a-walkthrough-with-javascripts-fetch-api-17be31755d28

### Conclusion

If we are unsure whether information already exists in a database, we retrieve the database with fetch using a GET request and then iterate through the response, searching for matching information.  In this example, we searched for a matching name using the .find() method, but other methods can be used.  For instance, if we need to anticipate finding several instances of matching database entries, we could use the .filter() method.  If no match is found, the new information can be added to the database with a POST request.  Alternatively, an existing database entry can be altered by using a PATCH or PUT request.

I have found the above-outlined steps to be useful in completing multiple tasks assigned to me as a software engineering student, and I hope they can be useful to you as well. Thanks for reading!