find by param node.js - javascript

I'm trying use find function to get data from my DB in mLab. I wrote this code, but I am getting an empty string.
My schema had id, name, course and grade.
It works for me when I want the file of the name but not for id. I guess it's because of the extra _id files that the mLab adds.
How do I fix it to get back the JSON that fits the id (let's say id=1)?
app.get('/getStudentById/:id', function(req, res) { //else if url path is getStudGrade with id param
Stud.find({id:req.params.id}, function(err, user){
if(err) throw err;
res.json(user);
mongoose.disconnect();
});
})
new edit
I have changed the filed 'id' to 'idStudent' in my DB and now it working.
Stud.find({ idStudent: req.params.id)}...)
but why?

So, assuming req.params.id actually has a value and /getAll shows that all your records have an id field set, the only thing that jumps out to me is the fact that your comparing a string to a Number i.e. req.params.id will be a string after deserialization but your schema dictates that the id field is numeric.
I am not sure if mongoose uses coercive comparison i.e. == over === (I doubt it), so in order to be more accurate you should parse your string to Number then do the comparison e.g.
Stud.find({ id: parseInt(req.params.id)}, ...)

Functions in query clause might not work, so to convert to Number just do:
Stud.find({ id: 1*req.params.id}, ...)

Related

SQLite table is only able to hold 1 row?

So, I have 2 tables, that I've added per the documentation, but something weird happens whenever I try to add a row to them. The data is written into the .db file, but whenever I query it, it only returns the first row. I can still update, and read these rows normally, but any data I write to them, just doesn't update the table. It's only the first row that get's written.
I've looked over all my statements, and I know they're right, since the first statement adds it to the table, but the second doesn't. I'm using the base configuration of sqlite3 from npm, per the docs, so I don't know what I'm doing wrong.
I don't have any errors, and the expected result, is that I'm able to add as many rows as I can
db.serialize(function() {
db.run("CREATE TABLE users (userId int, user varchar(255))");
db.run("CREATE TABLE notes (userId int, uuid varchar(50), name varchar(255), noteData varchar(1024), file BLOB(21845))")
});
db.run("INSERT INTO users (userId, user) VALUES (0, 'User')")
db.run(`INSERT INTO notes (userId, uuid, name, noteData) VALUES (0, 'uuid', 'First Note','This will be readable.')`)
//This statement will add the data to the file, but the query won't read it.
db.run(`INSERT INTO notes (userId, uuid, name, noteData) VALUES (1, 'uuid2', 'First Note','This will not show.')`)
db.get("SELECT * FROM notes",[],(err,row)=>{console.log(row)})
Also, this is not an asynchronous problem. In the example, I added the last line, but it's not actually in my code. I'm requesting it minutes later, and I can confirm the text is in the database, it just decides not to read it.
Your second insertion into notes table looks like has syntax error because of using additional single-quote.
I've changed by using two single-quotes at db-fiddle.com and it's working, but i'm not sure why you don't get an exception.
INSERT INTO users (userId, user) VALUES (0, 'User');
INSERT INTO notes (userId, uuid, name, noteData) VALUES (0, 'uuid', 'First Note','This will be readable.');
INSERT INTO notes (userId, uuid, name, noteData) VALUES (1, 'uuid2', 'First Note','This won''t.');
SELECT * FROM notes;
Ref for using two single-quotes; https://www.sqlite.org/faq.html#q14
Turn out I needed to use db.all. db.get returns only the first row.

How to prevent the sequelize from creating the output clause

When I do a create using sequelize it returns me the response i.e. the newly created entry row in the response,
Sequelize Create Object Code:
let createdObj= await sequelize.ModelName.create(modelObject,{ transaction :t, //more options can be added here, need some value of option that prevents the output inserted })
Below is the query created:
INSERT INTO [TABLE_NAME] ([COL1],[COL2],[COL3],[COL4]) OUTPUT INSERTED.* VALUES (#0,#1,#2,#3,#4)
Now I don't want the output clause to be part of the query, I want a simple insert like:
INSERT INTO [TABLE_NAME] ([COL1],[COL2],[COL3],[COL4]) VALUES (#0,#1,#2,#3,#4)
I don't want the output clause to be part of the query.
How can I achieve this in at the query level as well as at the model level? In some Create operations, I want the output clause and in some create operations, I don't want.
EDIT 1
On Further research I found an option called { returning: false } this does what is required i.e. create an insert query like this INSERT INTO [TABLE_NAME] ([COL1],[COL2],[COL3],[COL4]) VALUES (#0,#1,#2,#3,#4) but now the Sequelize is breaking because it's expecting those values back in return idk why?
C:\Users\MG265X1\project\node_modules\sequelize\lib\dialects\mssql\query.js:389
id = id || results && results[0][this.getInsertIdField()];
^
TypeError: Cannot read property 'id' of undefined
at Query.handleInsertQuery (C:\Users\MG265X1\project\node_modules\sequelize\lib\dialects\mssql\query.js:389:39)
Turns out if an autoIncrementAttribute is present in the model, it will look for the output clause, removing the attribute {autoIncrement: true } from the model hasn't helped as IDENTITY_INSERT cannot be null. How do I move ahead on this??
Edit 2 I could get it working with a combination of { returning: false } and {hasTriggers: true}. Have hasTriggers Attribute as true in your Model, this will allow you to single creates but for bulk Creates pass option returning: false at the time of bulkCreate.
Note: When using bulkCreate with { returning: false } you'll not be able to get the autogenerated Id, It's a trade-off that we had to live with as we want
bulkCreate to work with triggers, we ended up fetching the Id later from DB
Seems I raised this issue but was closed as it wasn't good SSCCE

Converting Mongo ID to String to do Comparison

I have a search feature that returns filtered data from my mongoDB based on a user's input for various filters. So, for instance I can do this and it works:
if (lastName) {
let arrlastName = [];
arrlastName = lastName.split(",");
_.each(arrlastName, (l, key, c) => {
arrlastName[key] = new RegExp(arrlastName[key], "i");
});
search['name.last'] = { $in: arrlastName };
}
The above returns a filtered data set where the results match whatever was passed in by the user in a comma separated list.
However, I am running into a challenge in comparing a user inputed value with an _id value in our mongo db. Of course, the _id I'm checking against here is not a string, but a mongo objectId -- that's the issue as far as I can tell. So I'm trying to figure out how I can convert either the input, or the _id, or both, to do a valid comparison. This was the initial code:
if (person) search['_id'] = person;
That doesn't work, because the value for person here is a string, and _id is not -- as I said, _id is a mongo objectId. So how can I do a type conversion to handle this check?
I tried this but it causes errors:
if (person) search['_id'].toString() = person;
What would the syntax look like for this kind of comparison?
In mongoDB you can use ObjectId.valueOf()
From the documentation
ObjectId("507c7f79bcf86cd7994f6c0e").valueOf()
will return the following string:
507c7f79bcf86cd7994f6c0e

duplicated key of id in mongodb

This code won't work, I got error of E11000 duplicate key error index error.
Student.update({_id: id, 'data.date':date}, {'$set': {'data.score': 50}}, {upsert: true},
function(err,result) {
res.json(1);
});
I have no clue how to solve it when I can do
Student.findOne({_id: id}, function(err,result){
res.json(result)
})
Any clue what's going on?
I see two possible problems:
You may have set some of the fields as unique and Mongo created an index for that field. For example if data.score would be unique then you couldn't have two documents with the same value and maybe other document already has a value of 50.
The solution would be to search for indexes and remove the ones that you don't want.
Maybe your search for {_id: id, 'data.date': date} doesn't return a result but not because you don't have a document with that id, but because it doesn't have that 'data.date' field that you search for. Then the upsert tries to insert a new document (because the search didn't find anything that has both '_id' equal to id and 'data.date' equal to date) but it fails to do so (because you already have a document with '_id' equal to id).
The solution would be to search only by _id if you're using upsert.

If i have a mongo document id as a string how do I query for it as an _id?

If i have a mongo document id as a string how do I query for it as an _id?
Will it work correctly to do .find({_id:'stringID'}) or do I need to convert it to a bson object first?
Do you mean you have the 24 hex digit string of an ObjectId?
Assuming that's what you mean, most drivers have a way to take a string and convert it to an ObjectId. In JavaScript that's:
.find({_id:new ObjectId("4f91bfcfaa7c5687a0c686d4")})
Updated to be a bit more useful for the node-native driver (from the documentation at https://github.com/christkv/node-mongodb-native):
// Get the objectID type
var ObjectID = require('mongodb').ObjectID;
var idString = '4e4e1638c85e808431000003';
collection.findOne({_id: new ObjectID(idString)}, console.log) // ok
collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined
If your _id values are strings, you may query them just like any other field. (Just remember, if you are setting custom values for _id, they must be kept unique, or you will get a duplicate key error. )
Here is an example in the Mongo JS Shell:
> db.test.insert({_id:"stringID1"})
> db.test.insert({_id:"stringID2"})
> db.test.insert({_id:"stringID3"})
> db.test.find({_id:"stringID1"})
{ "_id" : "stringID1" }
>
Is this what you were looking for? I hope I did not misunderstand your question!
Mongoose auto casts the string _id to ObjectId when you use findByID, so you can query using the string _id.
Also remember that any input coming into your API from req.body or req.params will all be type string so you will need to type cast if needed..., but as mentioned, mongoose does that for you so you can just leave _id in the string format it comes in as.

Categories