MongoDB does not search for documents - node.js

but I cant find any items after ID,
Calendar.model inside is doc:
/* 1 */
{
"_id" : ObjectId("5a3425b58399c6c26cf1c848"),
"doctorID" : ObjectId("5a31392cc99fe923c0810096"),
"doctor" : "Bartłomiej Flis",
"calendar" : []
}
And in nodeJS API I am trying to find the doc using function:
router.get('/list-of-dates', (req, res)=> {
Calendar.find({ doctorID : req.query.doctorID})
.then((Calendar)=>{
console.log(Calendar)
res.send(Calendar)
})
.catch((err)=>{
console.log(err)
})
});
the value of req.query.doctorID is string -> 5a31392cc99fe923c0810096
Anyone can tell me why this function can't find any item? I think it is the fault that in the database variable doctorID is as ObjectId and in the API req.query.doctorID is a string, how to improve it in the API to work.

First, import in the beginning of the file the following:
const ObjectID = require('mongodb').ObjectId;
Then, change your search query to (i.e. wrap it into the ObjectId() function)
{ doctorID: ObjectId( req.query.doctorID ) }
What is the difference? MongoDB stores keys in ObjectId type, whereas you are trying to find something with type String. You were correct. That's why you do not get anything.
Let me know if that helps.

Related

Elasticsearch with node.js how to make unique field when insert document to an index

I'm developing search engine to my project and i'm using Elasticsearch and node.js for the server.
Every night I have a parser that scrap data from some website and insert it to the db.
For now it duplicates the data that I already have.
Can I make a unique field inside the index when insert a document for example title : {unique : true} and by that it will not insert me a document that come with this title
Here is my code :
async function insertManual(manual) {
return new Promise(async (resolve, reject) => {
const result = await client.index({
index : 'completeindexthree',
body : {
brand : manual.brand,
category : manual.category,
url : manual.url,
title : manual.title, // example {unique : true}
parsingData : new Date().toString()
}
})
await client.indices.refresh({index: 'completeindexthree'})
resolve(result);
})
}
the second is , how can i delete all my duplicates that already got in by title from that index in node.js not from logstach ?
Tldr;
Yes it is possible, not by using the unique keyword though.
According to the documentation, if you set an _id and this id exist already it will be replaced/overwrite
If the target is an index and the document already exists, the request updates the document and increments its version.
Furthermore you will find this section
Using _create guarantees that the document is only indexed if it does not already exist.
To fix
You should set an _id per document and use the create
Your code may look like the following:
async function insertManual(manual) {
return new Promise(async (resolve, reject) => {
const result = await client.create({
index : 'completeindexthree',
id: manual.id, // <- Here is your unique id.
body : {
brand : manual.brand,
category : manual.category,
url : manual.url,
title : manual.title, // example {unique : true}
parsingData : new Date().toString()
}
})
await client.indices.refresh({index: 'completeindexthree'})
resolve(result);
})
}
If you don't give an id, elastic search creates a unique id, if you do, it creates the id you gave.
payload should be like this
{
id:"you_unique_id",
body:{foo,"bar"}
}

$in function of mongo db is not working in nodejs as except :(

i want to get all the document from mongo db by the number list provided by the user but
the problem i m facing here is this ...
when i pass the value hardcoded the $in function works fine
but when i pass the req.body.userlist then it give me an empty array although the values are same
routes.post(/contect,function(req,res){
var userList = req.body.userList;
var contectList = ["3423432","23432423","32342"];
console.log(userList); //output ["3423432","23432423","32342"]
User.find({
"phoneNumber" : {
"$in":contectList
}
}.then(function(data){
console.log(data);
})
any one help whats wrong here
problem solved Thanks to Anthony Winzlet
the solution was simple all i need to parse the input as Anthony winzlet said
`You are passing string through postman. Try to parse it User.find({
"phoneNumber"
: { "$in": JSON.parse(userList) }}) – Anthony Winzlet`
it should be an array, so try using the spread operator.
$in
{ phonenumber: { $in: [...conectList] } }

Dynamic URL with mongo method

Regarding these post : Mongoose prototype : how to insert an url dynamically?
I'm looking to do pretty much the same (URI dynamically insert).
The solution provided is good but I do not understand some things...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PicturesSchema = new Schema({
album : { type : String, required : true, trim : true },
pictures : { type : Array, required : false, trim : true }
});
PicturesSchema.virtual('pictureUrls').get(function() {
return this.pictures.map(function(picture) {
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
});
});
var Pictures = mongoose.model('Pictures', PicturesSchema);
// Demo:
var pictures = new Pictures({
album : 'album1',
pictures : [
'1434536659272.jpg',
'1434536656464.jpg',
'1434535467767.jpg'
]
});
console.log( pictures.getPics() );
The given solution injects a "virtual field" in addition to retaining the "pictures" field with the name of the images (without URL).
How to retain only the field "PicturesURL" containing the full URL of the image without displaying a redundancy with the "Pictures" field?
How to retrieve and display the JSON format query results as it knowing that data.ToJson returns an error: has no method 'toJson'?
Pictures.find().exec(function(err, data){
if(err){
console.log(err);
}
console.log('%j', data.toJSON({ virtuals : true }) );
});
A strategy to store only the picture url without the picture would be to create a Mongoose middleware on save.
You could then populate the picture field with the name of the picture, and the full url will be the one stored in the database and later retrieved.
For example:
PictureSchema.pre('save', function (next){
if (this.isModified(pictureUrls){
this.pictureUrls = this.pictureUrls.map(function(picture){
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
})
}
});
With this solution, every time you modify the pictures array, it will go over every element of the array and add the s3 path.
Since it won't be a virtual, it will be easier for you to use the model with event using toObject or toJson.

mongoose-encryption and updating objects

I know the mongoose-encryption doc states:
update will work fine on unencrypted and unauthenticated fields, but will not work correctly if encrypted or authenticated fields are involved.
And I've observed that when I use the mongoose create method that my fields are encrypted into the _ct field. However if I then use findByIdAndUpdate to update my object I see the fields are created in plain text (as output from mongodb console via find command).
From save
> db.tenants.find().pretty()
{
"_id" : ObjectId("554b7f8e7806c204e0c7589e"),
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0
}
After findByIdAndUpdate
> db.tenants.find().pretty()
{
"_id" : ObjectId("554b7f8e7806c204e0c7589e"),
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0,
"userId" : ObjectId("55268f43cbfc87be221cd611"),
"social" : "123-45-6789",
"last" : "bar",
"first" : "foo"
}
Is there a recommended strategy for updating objects and maintaining the encryption with mongoose-encryption?
As you quoted, the documentation for mongoose-encryption clearly tells that it does not work for update.
https://github.com/joegoldbeck/mongoose-encryption
Mongoose update hook is little tricky as well.
What you can do potentially is model your collection in such a way that fields which needs to be encrypted are a separate collection altogether and in the paren collection just link them via ids.
Person = {
_id: <ObjectId>
name: Blah
..
..
documents: [
{ 'doc_id': <ObjectId1> },
{ 'doc_id': <ObjectId2> },
]
}
Documents = [
{
"_id" : <ObjectId1>,
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0
}
...
...
]
This will increase code reuse as well.
I have implemented an strategy that i don´t think it is most efficient but it works.
I need to have all my data in database encrypted so i can´t use the above approach.
What i did is to create an update function that finds the document i want to modify, then i construct a new schema object and assing the _id of the found document to the new object.
Then i delete the original document and after that save the new object wich has the original _id. The only problem i found is that mongoose throw an error because duplicated _id that is printed in the console but it still works and _id aren´t duplicated.
I have tried replacing the_id and traking the document with another property but it still throw that error, anyway data is stored as expected.
exports.update= (req, res, next) => {
Solucion.findOne({_id: req.params.id})
.then(document => {
if (!document) {
res.status(404).json({
message: notFoundMessage,
data: null,
error: null
})
} else {
const solucion = new Solucion({
_id: document._id,
identificacion: document.identificacion,
informacion: document.informacion,
estado: req.body
})
Solucion.deleteOne({_id: document._id})
.then(() => {return solucion.save()})
.then(result=> {
return res.status(201).json({
message: editedSavedMessage,
data: result,
error: null
});
})
.catch(err => {
errorHandler.errorHandler(err, res);
})
}
})
};
UPDATE 29/07/2020
I have found that if you use the save method using the same _id, data is stored encrypted but Mongo creates your schema structure but with all values set to null.
Beyond that it seems to work as expected as data is not visible in DB.

Nodejs,mongodb - using $nin or $in for object ids or _id

I am using Nodejs, mongodb database. We can use $nin like this
Model.find({ uname : { $nin : ["sachin","saurav"] } }....
above words for normals elements like uname and others. But for object ids(_id), ..
Model.find({_id : {$nin : ["6534767457dfgbyb23","wtvwt3wy5etvdh"] } } ...
above line not giving error, it is showing correctly..
var ObjectID = require('mongodb').ObjectID;
var a = new ObjectID("sdfsdznfsdz");
var b=new ObjectID("sdfjwneufhq2rfwefsd");
Model.find({_id : { $nin : [a,b] } }...
above also not giving error...
The problem is, I cant write manually like a,b,c,d...
I have to store all those a,b,c,d... in some variable in some correct format, and have to do like this
Model.find({_id : {$nin : variable } }
or
Model.find({_id : {$nin : [variable] } }
I tried this
var string = a+","+b //this didnt work, error : invalid object id
var string = "nfw34qfhrs9"+","+"u89tgngnfdb" //this also same error
var string = "\"jn4tr43r\"" + "," + "\"ansfuw37fe\"" //this also same error
What should I do? the thing is, I should get all items except those items with those _ids.
The way $nin works in mongo is that it takes an array of values to check.
The code:
var string = a+","+b Doesnt make this a valid array. as you're creating a string with the value sdfsdznfsdz, u89tgngnfdb
So $nin is treating the array as that value, not the way you're trying to implement.
Solution to do what you want is to create an array with those values.
So something like:
var ids = new Array( new ObjectId("1124edcef241"), new ObjectId("56943decfeca845") );
// Dont put [ ] as a parameter. Just send a variable thats an array
Model.find( {_id : { $nin : ids } } );
...
Just incase you're a tad hazy regarding arrays, I suggest having a read of this:
http://www.w3schools.com/js/js_obj_array.asp
Not able to comment yet, but just wanted to add here that new ObjectID() wasn't working for me, but new ObjectId() (lowercase d) did work. Hope this helps someone.

Resources