Writing Documents
This page explains how to create, update, and delete MongoDB documents through RESTHeart’s REST API.
🔧 Configuration
Create the Inventory Collection
The example requests on this page use the inventory collection. If not already created, run the following:
cURL
curl -i -X PUT [INSTANCE-URL]/inventory -H "Authorization: Basic [BASIC-AUTH]"
curl -i -X POST [INSTANCE-URL]/inventory?wm=upsert -H "Authorization: Basic [BASIC-AUTH]" \
-d '[
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]'
HTTPie
http PUT [INSTANCE-URL]/inventory Authorization:"Basic [BASIC-AUTH]"
echo '[
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]' | http POST [INSTANCE-URL]/inventory wm==upsert Authorization:"Basic [BASIC-AUTH]"
JavaScript
const data = [
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
];
await fetch('[INSTANCE-URL]/inventory', {
method: 'PUT',
headers: { 'Authorization': 'Basic [BASIC-AUTH]' }
});
await fetch('[INSTANCE-URL]/inventory?wm=upsert', {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Authorization': 'Basic [BASIC-AUTH]' }
});
HTTP Methods for Writing Data
RESTHeart uses standard HTTP methods for database operations:
HTTP Method | Purpose |
---|---|
POST |
Create new documents (generates a new ID if not specified) |
PUT |
Replace existing documents or create with specified ID |
PATCH |
Update specific fields in existing documents |
DELETE |
Remove documents |
Content Types
JSON Format (Default)
For write operations, the default content type is application/json
:
POST /inventory HTTP/1.1
Content-Type: application/json
{
"name": "Product XYZ",
"price": 99.99,
"available": true,
"details": {
"color": "red",
"size": "medium"
}
}
Form Data Support
You can also use the following formats (Content-Type):
-
application/x-www-form-urlencoded
-
multipart/form-data
These formats are automatically converted to JSON documents:
POST /collection HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
name=Product%20XYZ&price=99.99&available=true&details=%7B%22color%22%3A%22red%22%2C%22size%22%3A%22medium%22%7D
Creating Documents
POST - Create with Generated ID
Use POST
to create a document and let MongoDB generate an ObjectId:
cURL
curl -i -X POST [INSTANCE-URL]/inventory \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"item": "rubber",
"qty": 15,
"size": {
"h": 2,
"w": 1,
"uom": "cm"
},
"status": "A"
}'
HTTPie
http POST [INSTANCE-URL]/inventory \
Authorization:"Basic [BASIC-AUTH]" \
item="rubber" \
qty:=15 \
size:='{"h": 2, "w": 1, "uom": "cm"}' \
status="A"
JavaScript
fetch('[INSTANCE-URL]/inventory', {
method: 'POST',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
item: "rubber",
qty: 15,
size: {
h: 2,
w: 1,
uom: "cm"
},
status: "A"
})
})
.then(response => {
if (response.ok) {
console.log('Resource created successfully');
console.log('Location:', response.headers.get('Location'));
} else {
console.error('Failed to create resource:', response.status);
}
})
.catch(error => console.error('Error:', error));
The response includes a Location
header with the new document’s URI:
HTTP/1.1 201 Created
Location: http://localhost:8080/inventory/61709f718bedc3055e218d7e
Tip
|
You can specify your own _id in the request body to avoid having MongoDB generate one.
|
PUT - Create with Specific ID
Use PUT
with the ?wm=upsert
parameter to create a document with a specific ID:
cURL
curl -i -X PUT "[INSTANCE-URL]/inventory/myCustomId?wm=upsert" \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"item": "pencil",
"qty": 55,
"size": {
"h": 10,
"w": 0.5,
"uom": "cm"
}
}'
HTTPie
http PUT "[INSTANCE-URL]/inventory/myCustomId?wm=upsert" \
Authorization:"Basic [BASIC-AUTH]" \
item="pencil" \
qty:=55 \
size:='{"h": 10, "w": 0.5, "uom": "cm"}'
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId?wm=upsert', {
method: 'PUT',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
item: "pencil",
qty: 55,
size: {
h: 10,
w: 0.5,
uom: "cm"
}
})
})
.then(response => {
if (response.ok) {
console.log('Resource created successfully');
console.log('Location:', response.headers.get('Location'));
} else {
console.error('Failed to create resource:', response.status);
}
})
.catch(error => console.error('Error:', error));
Updating Documents
PUT - Replace Document
PUT
replaces an existing document completely:
PUT /inventory/myCustomId HTTP/1.1
{
"item": "pencil",
"qty": 60,
"size": {
"h": 15,
"w": 0.5,
"uom": "cm"
}
}
Warning
|
This replaces the entire document. Any fields not included in the request will be removed. |
PATCH - Update Specific Fields
PATCH
modifies only the specified fields:
cURL
curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"qty": 75,
"status": "B"
}'
HTTPie
http PATCH [INSTANCE-URL]/inventory/myCustomId \
Authorization:"Basic [BASIC-AUTH]" \
qty:=75 \
status="B"
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId', {
method: 'PATCH',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
qty: 75,
status: "B"
})
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This only updates the qty
and status
fields, leaving all other fields unchanged.
Advanced Update Techniques
Updating Nested Fields with Dot Notation
Access nested document fields and array elements using dot notation:
cURL
curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"size.h": 20
}'
HTTPie
http PATCH [INSTANCE-URL]/inventory/myCustomId \
Authorization:"Basic [BASIC-AUTH]" \
size.h:=20
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId', {
method: 'PATCH',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"size.h": 20
})
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This updates only the height property within the size object.
For array elements:
cURL
curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"tags.1": "office"
}'
HTTPie
http PATCH [INSTANCE-URL]/inventory/myCustomId \
Authorization:"Basic [BASIC-AUTH]" \
tags.1="office"
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId', {
method: 'PATCH',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"tags.1": "office"
})
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This updates the second element of the tags
array.
MongoDB Update Operators
Use MongoDB’s update operators in PATCH
requests for more complex updates:
cURL
curl -i -X PATCH [INSTANCE-URL]/inventory/myCustomId \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"$inc": { "qty": 1 },
"$push": { "tags": "school" },
"$unset": { "discontinued": "" },
"$currentDate": { "lastModified": true }
}'
HTTPie
http PATCH [INSTANCE-URL]/inventory/myCustomId \
Authorization:"Basic [BASIC-AUTH]" \
Content-Type:application/json \
'\$inc:={"qty": 1}' \
'\$push:={"tags": "school"}' \
'\$unset:={"discontinued": ""}' \
'\$currentDate:={"lastModified": true}'
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId', {
method: 'PATCH',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"$inc": { "qty": 1 },
"$push": { "tags": "school" },
"$unset": { "discontinued": "" },
"$currentDate": { "lastModified": true }
})
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This:
- Increments qty
by 1
- Adds "school" to the tags
array
- Removes the discontinued
field
- Sets lastModified
to the current date/time
Tip
|
See MongoDB Update Operators for all available operators. |
Aggregation Pipeline Updates
Since RESTHeart 7.3, you can use MongoDB’s aggregation pipeline for updates:
PATCH /inventory/myCustomId HTTP/1.1
[
{
"$set": {
"tags": {
"$concatArrays": ["$tags", ["office", "school"]]
}
}
}
]
This adds "office" and "school" to the existing tags
array.
Deleting Documents
Use the DELETE
method to remove documents:
cURL
curl -i -X DELETE [INSTANCE-URL]/inventory/myCustomId \
-H "Authorization: Basic [BASIC-AUTH]"
HTTPie
http DELETE [INSTANCE-URL]/inventory/myCustomId \
Authorization:"Basic [BASIC-AUTH]"
JavaScript
fetch('[INSTANCE-URL]/inventory/myCustomId', {
method: 'DELETE',
headers: {
'Authorization': 'Basic [BASIC-AUTH]'
}
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
Bulk Operations
Perform operations on multiple documents with a single request.
Bulk Inserts
Create multiple documents at once:
cURL
curl -i -X POST [INSTANCE-URL]/inventory \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '[
{ "item": "journal", "qty": 25, "status": "A" },
{ "item": "notebook", "qty": 50, "status": "A" },
{ "item": "paper", "qty": 100, "status": "D" },
{ "item": "planner", "qty": 75, "status": "D" },
{ "item": "postcard", "qty": 45, "status": "A" }
]'
HTTPie
echo '[
{ "item": "journal", "qty": 25, "status": "A" },
{ "item": "notebook", "qty": 50, "status": "A" },
{ "item": "paper", "qty": 100, "status": "D" },
{ "item": "planner", "qty": 75, "status": "D" },
{ "item": "postcard", "qty": 45, "status": "A" }
]' | http POST [INSTANCE-URL]/inventory \
Authorization:"Basic [BASIC-AUTH]" \
Content-Type:application/json
JavaScript
fetch('[INSTANCE-URL]/inventory', {
method: 'POST',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify([
{ item: "journal", qty: 25, status: "A" },
{ item: "notebook", qty: 50, status: "A" },
{ item: "paper", qty: 100, status: "D" },
{ item: "planner", qty: 75, status: "D" },
{ item: "postcard", qty: 45, status: "A" }
])
})
.then(response => {
if (response.ok) {
console.log('Resource created successfully');
console.log('Location:', response.headers.get('Location'));
} else {
console.error('Failed to create resource:', response.status);
}
})
.catch(error => console.error('Error:', error));
Bulk Updates
Update multiple documents using a filter:
cURL
curl -i -X PATCH '[INSTANCE-URL]/inventory/*' \
--data-urlencode 'filter={"qty":{"$gt":50}}' \
-H "Authorization: Basic [BASIC-AUTH]" \
-H "Content-Type: application/json" \
-d '{
"highQuantity": true
}'
HTTPie
http PATCH '[INSTANCE-URL]/inventory/*?filter={"qty":{"$gt":50}}' \
Authorization:"Basic [BASIC-AUTH]" \
highQuantity:=true
JavaScript
fetch('[INSTANCE-URL]/inventory/*?filter=' + encodeURIComponent('{"qty":{"$gt":50}}'), {
method: 'PATCH',
headers: {
'Authorization': 'Basic [BASIC-AUTH]',
'Content-Type': 'application/json'
},
body: JSON.stringify({
highQuantity: true
})
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This adds the highQuantity
field to all documents with a quantity greater than 50.
Bulk Deletes
Delete multiple documents matching a filter:
cURL
curl -i -X DELETE '[INSTANCE-URL]/inventory/*' \
--data-urlencode 'filter={"status":"D"}' \
-H "Authorization: Basic [BASIC-AUTH]"
HTTPie
http DELETE '[INSTANCE-URL]/inventory/*?filter={"status":"D"}' \
Authorization:"Basic [BASIC-AUTH]"
JavaScript
fetch('[INSTANCE-URL]/inventory/*?filter=' + encodeURIComponent('{"status":"D"}'), {
method: 'DELETE',
headers: {
'Authorization': 'Basic [BASIC-AUTH]'
}
})
.then(response => {
if (response.ok) {
console.log('Write request executed successfully');
} else {
console.error('Write request failed:', response.status);
}
})
.catch(error => console.error('Error:', error));
This deletes all documents with a status of "D".
Important
|
Bulk operations require special permissions. The default admin user can execute them, but other users need the appropriate permissions.
|
Write Modes
The ?wm=
query parameter can override the default write mode for each HTTP method:
Write Mode | Description | Example |
---|---|---|
insert |
Create a new document, fail if ID exists |
|
update |
Update an existing document, fail if ID doesn’t exist |
|
upsert |
Update if exists, create if doesn’t exist |
|
Important
|
The wm parameter requires special permissions. The default admin user can use it, but other users need the allowWriteMode permission.
|
Reference: Default MongoDB Operations
This table shows which MongoDB operation is executed based on the HTTP method and write mode:
Write Mode | Method | URI | MongoDB Operation | Description |
---|---|---|---|---|
insert |
POST |
|
|
Create document with generated ID |
insert |
PUT |
|
|
Create document with specified ID |
insert |
PATCH |
|
|
Insert with update operators |
update |
POST |
|
|
Replace existing document |
update |
PUT |
|
|
Replace existing document |
update |
PATCH |
|
|
Update specific fields |
upsert |
POST |
|
|
Replace or create with body ID |
upsert |
PUT |
|
|
Replace or create with URI ID |
upsert |
PATCH |
|
|
Update fields or create |
Bold entries indicate default behavior when no wm
parameter is specified.