MongoLab API Update: message: "Update object is missing." - mlab

Unable to update data in the data base. The above is a request link.
https://api.mongolab.com/api/1/databases/my-db/collections/my-coll/52f7b875e4b0e615e67f0a41?jsonbody=[{"_id":"52f7b875e4b0e615e67f0a41","like":"true"}]&apiKey=my_api_key
Got. 400 Bad Request error and message: "Update object is missing."
Or anyone can give an example to update mongodb via REST API in java would be very helpful.
Thanks.

It looks like you're missing the actual update spec, which should be the body of the PUT request. The MongoLab Data API docs include example of how to do that from jQuery, the key bits of which I've copied below for your convenience.
$.ajax( { url: 'https://api.mongolab.com/api/1/databases/my-db/collections/my-coll?apiKey=myAPIKey&q={"_id":1234}',
data: JSON.stringify( { "$set" : { "x" : 3 } } ),
type: "PUT",
contentType: "application/json" } );
Note that the $set update operator is not part of the url, but the body (which you specify in jQuery using the data field).

Related

URL parameter vs post form data

URL parameter or post form data; which is more computationally efficient for a backend API to query?
example:
GET : user/:id
POST: user/ { "id": "some_id" }

REST API - Endpoint syntax - get item by property - not by id

I'm implementing my first REST API, and I have a question about the syntax of the URL endpoints.
I know that I should use these endpoint for get, create, update and delete:
Get list of items
Method: GET, Url: /api/items
Get item by id
Method: GET, Url: /api/items/:id
Add item (new item data in the request body)
Method: POST, Url: /api/items
Modify item (modified item data in the request body)
Method: PUT, Url: /api/items/:id
Delete item
Method: DELETE, Url: /api/items/:id
But lets say the interface of item is
interface item
{
id: string;
name: string;
}
What should be the request url for getting an item by it's name?
I can't use Method: GET, Url: /api/items/:name, because this will match the get-by-id request. So how should I syntax this endpoint?
There is no standard REST URI syntax unless you are doing OData for example. You have perfect freedom designing your own URIs, even /resource/{id} is perfectly valid.
What I like to do is end the URIs of collections with / and use queries for filtering collections. So I would do /api/{version}/items/?name={name} if they have unique names and you expect an item instead of a collection, then I would do it this way: /api/{version}/items/name:{name}. But this is my style.
From client perspective the URI syntax is totally irrelevant, because the server gives the valid URI templates to the client according to the HATEOES constraint. If you thought otherwise, then probably you are building a CRUD API instead of a REST API.
You chould use a filter on the collections endpoint like:
Method: GET, Url: /api/items?name=foo
This filter could return all items which have a foo string in them (depending on how you want to handle wildcards in the search / filter term), e.g. the response could be a collection of items:
{
"data": [
{
"id": "d079d8e9-4d24-4514-b356-78587f6c2ba9",
"name": "foo"
},
{
"id": "7f5e558c-6a7f-4ebe-8f4f-a2d029a803ed",
"name": "foo bar"
}
]
}
If you want the response to return a single resource you could also use the name as identifier and apply the scheme from above using the name, e.g.
Method: GET, Url: /api/items/:name

Cannot read property 'length' of undefined on one GET request

working with a MEAN Stack and I have three GET requests for the same URL/Route. One is to get a generalised summary of long-term emotions, the other is to get a summary of emotions by dates entered, and lastly, a summary of emotions related to a user-entered tag associated with individual emotion entries.
My first GET request is throwing no issues but the second GET request throws an error: Cannot read property 'length' of undefined
The error points to the following line:
48| each emotion in dateEmotions
Below is the relative code associated with the error:
Jade
each emotion in dateEmotions
.side-emotions-group
.side-emotions-label
p.emotion-left= emotion.emotionName
p.pull-right(class= emotion.emotionLevel) (#{emotion.emotionLevel}%)
.side-emotions-emotion.emotion-left
GET Request
module.exports.emotionsListByDates = function (req, res) {
Emo.aggregate([
{ $match :
{ "date" : { $gte: ISODate("2018-04-09T00:00:00.000Z"), $lt: ISODate("2018-04-13T00:00:00.000Z") } }
}, { "$group": {
"_id": null,
"averageHappiness": {"$avg": "$happiness"},
"averageSadness": {"$avg": "$sadness"},
"averageAnger": {"$avg": "$anger"},
"averageSurprise": {"$avg": "$surprise"},
"averageContempt": {"$avg": "$contempt"},
"averageDisgust": {"$avg": "$disgust"},
"averageFear": {"$avg": "$fear"},
}}
], function (e, docs) {
if (e) {
res.send(e);
} else {
res.render('dashboard', {
title: "ReacTrack - User Dashboard",
pageHeader: {
title: "User Dashboard",
strapline: "View your emotional data here."
},
dateEmotions: docs
})
}
});
};
This question is already getting pretty long, but I have another GET Request pointed to that URL and it is not throwing any errors, and the only difference is that I am not matching the db records by date in that query. I can post the working code if need be.
Edit
After some experimenting, I am able to get each of the three routes working individually if I comment out the other two. It's when multiple routes pull in the multiple requests that causes issues. For example, here are the routes at present where the ctrlDashboard.emotionsListByDates is working:
// Dashboard Routes
//router.get(/dashboard', ctrlDashboard.emotionsListGeneralised);
router.get('/dashboard', ctrlDashboard.emotionsListByDates);
//router.get('/dashboard', ctrlDashboard.emotionsListByTag);
If I comment out two routes and leave one running, and comment out the respective each emotion in emotions each emotion in dateEmotions and each emotion in tagEmotions blocks in the Jade file and leave the correct one uncommented, then that route will work, it seems to be when I am firing multiple routes. Is this bad practice, or incorrect? Should all queries be in the one GET request if on the same URL?
Thanks.
Apologies, new to routing and RESTful APIs but after some researching into the topic, I now understand the fault.
I assumed that the URL used in routing was the URL you wanted the data to populate...which it still kinda is, but I thought if I wanted to populate the dashboard page, I had to use that exact route and I did not realise I could post the data to different URL routes and take the data from those URLs to populate the one page.
Fixed by adding /date and /tag to those routes and using AJAX to perform those requests and populate the main page.
Thanks all.
I have the same problem but I'm using React+Redux+Fetch. So is it not a good practice dispatch more the one request in the same time and from the same page to a specific url?
I would know what causes that problem. I've found some discussions about it could be a mongoose issue.
My code:
MymongooObject.find(query_specifiers, function(err, data) {
for (let i = 0; i < data.length; ++i) {
...
}
}
Error:
TypeError: Cannot read property 'length' of undefined

Non-standard REST API in Backbone js

I am building Backbone.js models backed by a legacy REST API. When I create a new resource on the server, rather than return the JSON of the newly created resource, it returns plain text of the id of the newly created resource, along with a relative URL in the Location header where the resource can be gotten.
For example, I POST:
{ "firstName": "Joe", "lastName": "Blow" }
to http://fakeserver.com/people and (on success) the body of the plain/text response might be: "1234". The status of the response is 201 and the Location header would be http://fakeserver.com/people/1234. If I GET from that Location URL, it will have
{ "id": 1234, "firstName": "Joe", "lastName": "Blow" }
How would I override the sync function on my model to accommodate this convention instead of the default Backbone.js conventions?
To clarify, there is no Backbone.js version of this yet - I am trying to create a new one. The old jQuery-only way of doing it was:
$.ajax({
type: 'POST',
url: submitURL,
data: $.toJSON(person),
success: function(data, status, request) {
showSuccessMessage();
closeDialog();
},
dataType: 'json',
contentType: 'application/json'
});
The details of the showSuccessMessage and closeDialog are unimportant - just to demonstrate that basically we are just ignoring the content of the response and throwing the original object away.
Handle the simple text response with parse:
http://backbonejs.org/#Model-parse
parse : function(response, options){
console.log(response, options);
var data = this.toJSON(): //current model to hash
data.id = response; <- assuming that response is a simple text plain id
return data;
}
You could also use sync to overwrite something in the ajax call(that is not supported in the options hash.
http://backbonejs.org/#Model-sync

mongodb insert and return id with REST API

New to Mongodb,trying to get _id after mongodb insert without a round trip.
$.ajax( { url: "https://api.mongolab.com/api/1/databases/xxx/collections/xx?apiKey=xxx",
data: JSON.stringify( [ { "x" : 2,"c1" : 34,"c2" : getUrlVars()["c2"]} ] ),
type: "POST",
contentType: "application/json" } );
Thanks
edit: Solved buy removing square bracers JSON.stringify( { "x" : 2,"c1" : 34,"c2" : getUrlVars()["c2"]} )
You can't get the _id of the object without waiting for a response because the _id is generated on the server. You need to attach a success call to your request. The id is actually returned as a $oid member within an _id object.
This is assuming you are using $.ajax to make the request and the MongoLab REST API as documented at http://support.mongolab.com/entries/20433053-rest-api-for-mongodb
For example:
$.ajax( { url: 'https://api.mongolab.com/api/1/databases/xxx/collections/xx?apiKey=xxx',
data: JSON.stringify( {"x" : 1 } ),
type: "POST",
contentType: "application/json"}
).success(function(returnedData) {
alert(returnedData._id["$oid"]);
});
What REST API are you using? MongoDB does not ship with a REST API that does what you are trying to do.
According to the MongoLab REST API docs, the square braces are for inserting multiple docs at a time. For a single document, you simply need to JSON.Stringify a single valid JSON (BSON) document.