Mongo and Node.js: unable to look up document by _id - node-mongodb-native

I'm using the Express framework and Mongodb for my application.
When I insert objects into the database, I use a custom ObjectID. It's generated using mongo's objectid function, but toString()ed (for reasons i think are irrelevant, so i won't go into them). Inserts look like this:
collection.insert({ _id: oid, ... })
The data is in mongo - i can db.collection.find().pretty() from mongo's cli and see it exactly as it's supposed to be. But when I run db.collection.find({_id: oid}) from my application, I get nothing ([] to be exact). Even when I manually hardcode the objectID that I'm looking for (that I know is in the database) into my query, I still can't get an actual result.
As an experiment, I tried collection.find({title: "test title"}) from the app, and got exactly the result I wanted. The database connection is fine, the data structure is fine, the data itself is fine - the problem is clearly with the _id field.
Query code:
var sid = req.param("sid");
var db = req.db;
var collection = db.get("stories");
collection.find({'_id': sid }, function(err, document) {
console.log(document.title);
});
Any ideas on how I can get my document by searching _id?
update: per JohnnyHK's answer, I am now using findOne() as in the example below. However, it now returns null (instead of the [] that i was getting). I'll update if I find a solution on my own.
collection.findOne({'_id': sid }, function(err, document) {
console.log(document);
});

find provides a cursor as the second parameter to its callback (document in your example). To find a single doc, use findOne instead:
collection.findOne({'_id': sid }, function(err, document) {
console.log(document.title);
});

Related

Autodesk Simple Viewer - "Could not list models. "

I'm trying to implement the code example in this repo:
https://github.com/autodesk-platform-services/aps-simple-viewer-dotnet
While launching in debugging mode, I get an error in the AuthController.cs says:
Could not list models. See the console for more details
I didn't make any significant changes to the original code, I only changed the env vars (client id, secret etc..)
The error is on the below function:
async function setupModelSelection(viewer, selectedUrn) {
const dropdown = document.getElementById('models');
dropdown.innerHTML = '';
try {
const resp = await fetch('/api/models');
if (!resp.ok) {
throw new Error(await resp.text());
}
const models = await resp.json();
dropdown.innerHTML = models.map(model => `<option value=${model.urn} ${model.urn === selectedUrn ? 'selected' : ''}>${model.name}</option>`).join('\n');
dropdown.onchange = () => onModelSelected(viewer, dropdown.value);
if (dropdown.value) {
onModelSelected(viewer, dropdown.value);
}
} catch (err) {
alert('Could not list models. See the console for more details.');
console.error(err);
}
}
I get an access token so my client id and secret are probably correct, I also added the app to the cloud hub, what could be the problem, why the app can't find the projects in the hub?
I can only repeat what AlexAR said - the given sample is not for accessing files from user hubs like ACC/BIM 360 Docs - for that follow this: https://tutorials.autodesk.io/tutorials/hubs-browser/
To address the specific error. One way I can reproduce that is if I set the APS_BUCKET variable to something simple that has likely been used by someone else already, e.g. "mybucket", and so I'll get an error when trying to access the files in it, since it's not my bucket. Bucket names need to be globally unique. If you don't want to come up with a unique name yourself, then just do not declare the APS_BUCKET environment variable and the sample will generate a bucket name for you based on the client id of your app.

get 'undefined' saveResult.entities after saveChanges [breezejs]

I tried to update one entity in my angularjs client using breezejs library. After calling saveChanges(), it can actually save back in the server and fetched on the client. However, the server did not return the response back. The saveResult.entities is undefined and pop up an error for me. When I took a look at the docs, it mentions 'Some service APIs do not return information about every saved entity. If your server doesn't return such information, you should add the pre-save, cached entity to saveResult.entities yourself'. Could anyone provide an example of how to do this?
This is the code when i am trying to do an update.
manager.saveChanges(entitiesToSave, null, (saveResult) => {
const savedRes = saveResult;
savedRes.entities = entitiesToSave;
return savedRes;
}).then(saveSucceeded);
On the server, you would need to construct the response for an update similar to the way it is for a create:
response.setContent(...); // entities
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());

Search with Relay doesn't include new results due to local cache

I've implemented a search-as-you-type component in React and Relay. It's roughly the same setup as search functionality using relay
It works as intended with one exception. New results from the server never appear when I retype a search I've already performed on the client. I looks like Relay always goes to the local cache in this case.
So, for example, say I've searched for 'foo' and didn't find any results. Now, seconds later, another user on the website creates this 'foo', but Relay will never query the server since the cached response to the 'foo' search was an empty result.
Is there a pattern or best practice for this scenario?
The query is as follows. I call this.props.relay.setVariables to perform the search:
initialVariables: {
search: '',
hasSearch: false
},
fragments: {
me: () => Relay.QL`
fragment on Viewer {
relationSearch(search: $search) #include(if: $hasSearch) {
... on User {
username
}
}
}
`
}
The answer seems to be to use this.props.relay.forceFetch with the search variables instead.
See https://facebook.github.io/relay/docs/api-reference-relay-container.html#forcefetch
Someone correct me if this isn't best practice.

How do you switch from SQL to Table Storage in Azure Mobile Services?

I've signed up for the free month trial of Azure, and I have created a Mobile Service. I'm using iOS, so I downloaded the model Todo app for iOS.
I am now trying to use Table Storage in the back end instead of a MSSQL store; I have found instructions on using Table Storage here: http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-table-storage/
However, my app is still storing todo items in the MSSQL storage. I've been told that I don't need to do anything in the client to make the switch, so I assume everything I need to do must be done in the node.js scripts. But I'm clearly missing something.
One thing that confuses me is that after I downloaded the generated node.js script for the Todo app, I didn't see anything in it that seemed to be explicitly talking to the MSSQL database.
Any pointers would be greatly appreciated.
EDIT:
here's my todoitem.insert.js:
var azure = require('azure-storage');
var tableSvc = azure.createTableService();
function insert(item, user, request) {
// request.execute();
console.log('Request received');
console.log(request);
var entGen = azure.TableUtilities.entityGenerator;
var task = {
PartitionKey: entGen.String('learningazure'),
RowKey: entGen.String('1'),
description: entGen.String('add something to TS'),
dueDate: entGen.DateTime(new Date(Date.UTC(2014, 11, 5))),
};
tableSvc.insertEntity('codedelphi',task, {echoContent: true}, function (error, result, response) {
if(!error){
// Entity inserted
console.log('No error on table insert: task created.');
request.respond(statusCodes.SUCCESS, 'OK.');
} else {
console.log('Houston, we have a problem. Entity not added to table.');
console.log(error);
}
});
console.log(JSON.stringify(item, null, 4));
}
tableSvc.createTableIfNotExists('codedelphi', function(error, result, response){
if(!error){
// Table exists or created
console.log('No error, table should exist');
} else {
console.log('We have a problem.');
console.log(error);
}
});
Mobile Services has the built in capability to handle talking to your SQL Database for you. When your script calls "request.execute()" that triggers whatever the request is (insert, update, delete, select) to be ran against the SQL database. Talking to Table Storage instead of SQL requires you to edit those scripts to explicitly talk to Table Storage (i.e. perform your insert, update, deletes, and reads). Today there is no magic switch which will change your "request.execute" from talking to SQL to talk to Table Storage. If you've already edited your scripts to talk to Table Storage and it's not working / you still see data stored in your SQL database, I would suspect that you are either still calling "request.execute" in your scripts, or you haven't pushed them to your Mobile Service (if you've pulled them down locally and then need to push them back to your service). If you've done all of the above, update your question with the Node.js script in question so we can see it.
As Chris pointed out, you are most likely still calling request.execute() from your table scripts. By design, this will explicitly talk to the MSSQL database you configured your application with. You will have to edit your table scripts to not perform "request.execute()" and instead interact with the TableService object.
If you follow the tutorial, and do the following:
1. Import the package.
2. Create the table service object.
3. Create an entity (and modify the variables to store the data you need)
4. Write the entity to your table service.
You should see data being written to table storage rather than SQL database.
Give it a shot and ping back, we'll help you out.

CouchDB save doc uri incorrect

I am really scratching my head over this one. I am using cloudant as my couchdb provider and attempting to save a document to my db. I first establish what my db is in the following code.
db = jQuery.couch.db("https://fullscore.cloudant.com/fullscore");
I do a console.log and see that the URI and name are correct in the object.
db.saveDoc(doc, {
success: function(data) {
console.log("posted");
},
error: function(status) {
console.log("failure");
}
});
However when I look at the post, it posts to: https://cloudant.com/https%3A%2F%2Ffullscore.cloudant.com%2Ffullscore/
Which as you can see is totally wrong. Obviously there is something built in to append onto cloudant.com ... anyone know how this can be overridden? Or perhaps its some other problem? I'm getting a 404 error.
--Ashley
To clarify the exact code, you need to set the URL prefix on your couch object, then use just the db name:
$.couch.urlPrefix = "https://username.cloudant.com";
var db = $.couch.db("dbname");
I'm guessing you're passing the full database URL in a place where you're only supposed to pass the database name (i.e. the latter "fullscore" part in https://fullscore.cloudant.com/fullscore"). You've probably already set up the host name at some earlier point in your program.

Resources