Argument passed in must be a string of 12 bytes - javascript

Hello guys i'm getting this message when i'm trying to delete an entry in my DB.
I have tried JSON.parse on the req.body,switched the routes in my routes file yet nothing seems to work.
this is my controller :
async function removeToy(req, res) {
try {
const { toyId } = req.params
const removedId = await toyService.remove(toyId)
res.send(removedId)
} catch (err) {
logger.error('Failed to remove toy', err)
res.status(500).send({ err: 'Failed to remove toy' })
}
}
this is the service :
async function remove(toyId) {
try {
const collection = await dbService.getCollection('toy')
await collection.deleteOne({ '_id': ObjectId(toyId)})
return toyId
} catch (err) {
logger.error(`cannot remove toy ${toyId}`, err)
throw err
}
}
also added a picture of how the DB looks like:
and the picture of the entire error :
appreciating any kind of help!

In your database you have an object whose _id is of type string.
In your query, you're casting (presumably) a string to an ObjectID, which is an object. Not only is the argument you're passing to ObjectId() not something that it supports (as the error indicates, see below), even if it would be valid, the query would result in 0 hits: after all "TZ23c" !== ObjectId("TZ23c").
Simply change .deleteOne({_id: ObjectId(toyId)}) to .deleteOne({_id: toyId}).
ObjectId() either takes no argument (it will return a new value) or it takes exactly 12 bytes (24 hexadecimal characters), for example: ObjectId("61e16f21f82a9db6a2094e78").
An ObjectId's string representation (ObjectId().toString()) is not an arbitrary string of characters: it's a timestamp, some values that identify which server generated it and some random values to prevent collisions. Not every string is a valid ObjectId.

As the message suggest your toyId passed to the function is with wrong lenght , it must be 12 bytes long , example:
mongos> ObjectId("x448c")
2022-01-14T13:43:51.427+0100 E QUERY [js] Error: invalid object id: length
:
#(shell):1:1
mongos>
The correct is:
mongos> ObjectId("61e16facafe3aa6023c221bb")
ObjectId("61e16facafe3aa6023c221bb")

Related

Mongodb using dynamic fields with $not

I programming in react, mongodb, nodejs and expressjs. I have a problem that I cannot solve. I would like to use dynamic fields from $not on the server. For example, the server gets the column name from the front and it is supposed to return the number of documents where the text is different from an empty string, i.e. ''. I've tried to do something like this(code below), but it doesn't help.
const query = {};
query[type] = { $not: '' };
User.countDocuments(query, (err, data) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true, data: data });
});
You are close, you probably were looking for $ne instead of $not. So changing it to
const query = {};
query[type] = { $ne: '' };
should fix the issue. This would find all documents where the dynamic type field does not equal ''. If you want to do the inverse, i.e. find all documents where the dynamic field equals an empty string, change it to:
query[type] = { $eq: '' };

Passing array of strings to a GraphQL query, convers to integers when embedded

I'm trying to figure out a way to pass an array of strings and embed it into a query (using React, GraphQL). The problem is it accepts the parameter as an array of strings, but converts it to a string when I embed it.
Let's say I have this function that makes a call to get some data. (I hardcoded the argument for now but it will be a variable as soon as I figure this out).
// here I'm calling the function
const query = getData.generate(["123", "456"]);
return GraphqlClient.query(query)
.then((e) => {
return e.data.oneAppProviders;
}) .......
// and here is the query with the embedded parameter. (Backend expects an array of strings.)
export default {
generate(id) {
// console.log(id) // output: ["123", "456"]
return { query : gql`{
oneAppProviders(id: ${id}) {
id
firstName
}
}
}}
When I run it, I get this error:
GraphQLError {message: "Syntax Error: Expected Name, found Int "456""
I guess, when I embed it, it converts it to integers...
If my array is ["123"], I get the following error:
[GraphQL error]: Message: Expected type [String], found 123.
I hope the question is clear enough. Thanks in advance.
Maybe this helps someone:
export const UserFlagsQuery = gql`
query($flags: [String!]!) {
user {
flags(where: { AND: [{ name_in: $flags }, { enabled: true }] }) {
name
enabled
}
}
}
`;
Use this query in a React Query component like this:
<Query
query={UserFlagsQuery}
variables={{
flags: ["flag1", "flag2", "..."],
}}
>
Thanks to #David Maze answer.
As a general rule you should avoid embedding data into query language strings like this. (What if the id variable is actually a string containing parentheses and curly braces? https://xkcd.com/327 is a more famous, if fictional, example of the potential problems you're facing.)
GraphQL supports top-level query parameters and you should use those here. If you make your query like
query Providers($ids: [ID!]!) {
oneAppProviders(id: $ids) {
id
firstName
}
}
most query libraries have a way to pass in additional parameters; so in your case that might look like
const query = gql`...`;
const variables = { ids: ids };
GraphqlClient.query(query, variables).then(...);
A simple solution to your problem is as follows:
let myarray = ["string1", "string2", "String3"];
let dataToSend = myarray.toString();
let gql`
{
passArray(data:${dataToSend}){
}
}`;

Pass data as object to mongoDb, use it as query and compare

I have a document in my mongoDB
I pass the object from my frontend (user should type something in input filed, for example he types 'test':
{'countdown': 'test'}
And then I pass it to my backend and want to check if he typed right
app.post('/answ', function(req, res) {
var query = req.body;
Model.find(query
, function(err, result) {
if (err) throw err;
if (result) {
if(result.length!== 0) {
res.json('ok');
} else {
res.json('not found');
}
} else {
res.send(JSON.stringify({
error : 'Error'
}))
}
})
});
So, if key-value pair exist, backend will return ok, otherwise not found.
It works for such simple object, but if I try to pass something like:
{'apilisttask': { 'port': '1', 'host': '2', 'path': '3', 'query': '4' } }
In this example user has 4 input fields, I gather all answers and pass it to the backend, but it doesn't give me ok even if the answers are right.
Could you please advice maybe a better approach to compare the data or how to fix the second comparison?
Since you are trying to find in an embedded document, you can not query embedded doc like that.
To query embedded doc, you need to do something like this:
Model.find({'apilisttask.port':query.apilisttask.port, 'apilisttask.host':query.apilisttask.host, ...}, function(err, result){
// ---
});
This should do the trick.

I have problems with findOneAndUpdate, does not return an error when one of the search data is undefined

When I do a search with "findOneAndUpdate" and one of my search parameters is "undefined" I do not get an error but is the object searched. this is the code:
var q = Q.defer();
var findOneQuery = {
_id: restId,
versionId: document.version // if this parameter is undefined
};
this.findOneAndUpdate(findOneQuery, {$set: document, $inc: {versionId: 1}}, {upsert: true, new: true}, function (updateError, updateDocument) {
if (updateError) {
q.reject(updateError);
}
else {
q.resolve(updateDocument);
}
});
return q.promise;
I think it should return an error if I'm wrong What should I do to search for the two parameters sent and not just by one of them?
You can easily write a wrapper method around findOneandUpdate that would precisely do what you want with your reqs.
function myFindOneAndUpdate(monObj,query,update,options,callback){
//validateINput check if the params in query object are undefined
if(validateInput(query)){
monObj.findOneAndUpdate(query,update,options,callback)
}else{
throw new Error('InvalidInput');
}
}
If parameter is undefined, then mongodb try to find records in which parameter is undefined. So it would not throw any error.
if you want that versionId should be never null/undefined. then you can validate inputs before passing to db query.
You can use this module:
https://www.npmjs.com/package/validator

redis zunionstore dynamically pass the sets

I want to use the zunionstore command on sets which i define at runtime, they are fetched dynamically so i never know what the sets are that i have to pass to the function.
syntax of zunionstore:
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
the parsed array contains the names of the sets.
client.zunionstore
(
'out',
parsed.length,
parsed,
function (err, res)
{
console.log(err);
if(!err)
{
client.zrevrange('out', 0, -1, 'withscores', function (err, res)
{
console.log(res);
if(!err)
{
//do stuff
}
});
}
}
);
as you can see i tried to pass the array containing the names but this doesn't work..
the error i get:
[Error: ERR syntax error]
Any ideas on how to solve this?
do you mean that you are having problems passing an array to a function? put all arguments into an array and call apply on the function: Passing an array as a function parameter in JavaScript
so, you have your parsed array, just add to it the other things like your 'out', parsed.length, etc, and call client.zunionstore.apply(this, array).

Categories

Resources