Properly handling duplicated key with node-mysql - javascript

I'm writing a registration form in my application, the user's name and the user's email must be unique.
I run a mysql database and use node-mysql (v 2.0.0) as driver.
When a user tries to use a name that is allready registered in the database, mysql raises the following error : Error: ER_DUP_ENTRY: Duplicate entry 'John' for key 'nickname', but in the Error object raised by node-mysql contains no usefull informations about the error :
console.log(JSON.stringify(err));
{"code": "ER_DUP_ENTRY", "errno": 1062, "sqlState": "23000", "index": 0}
Where can I get the involved entry and key ? I need to know which of the key nickname or the key email is responsible for the duplicate key error, so that I can warn the user.
I know I can find this info doing err.toString() and parsing the result (which contains is the mysql error string itself) but I would like to know if there is a better way to do so.

The reason you don't see the message and other Error properties is that some of those "standard" properties are not set as enumerable and as a result JSON.stringify() does not pick them up.
You could add a toJSON() to Error that correctly returns serializes all properties. This method is automatically called by JSON.stringify() if it detects its existence on the value you pass in. Example:
var config = {
configurable: true,
value: function() {
var alt = {};
var storeKey = function(key) {
alt[key] = this[key];
};
Object.getOwnPropertyNames(this).forEach(storeKey, this);
return alt;
}
};
Object.defineProperty(Error.prototype, 'toJSON', config);

Related

Firebase - Getting data from child sometimes returns unknown

I'm building an Android app with React Native using Firebase to implement chat between users. I'm running tests now and found out that, on occasion, sending chat messages produces the following exception and crashes the app:
Reference.child failed: First argument was an invalid path = "undefined". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]"
This is the function that sends messages to the Firebase Realtime Database, triggered whenever the "send message" button is pressed:
sendMessageToFirebase(chatId, userId){
let newMessage = {created: new Date().toJSON(), text: this.state.textInput}
//getting messages data from firebase
let data = {};
console.log('REF:' + firebase.database().ref('chats'));
dataRef = firebase.database().ref('chats').child(chatId);
console.log('REF WITH CHILD: ' + dataRef);
dataRef.on('value', datasnap=>{
data = datasnap.val()
//the following function rewrites the dictionary fetched from FB to add the new message
data = this.rewriteFirebaseChatData(data, userId, newMessage);
})
//sending the data
dataRef.set(data)
this.loadMessagesFromFirebase(chatId);
}
The first console log, with just the ref, will always print, but on a seemingly random basis, the second ref will not and I'll get the exception, so I can assume that's where the issue is. Is there a way to fetch data from the child reliably?
If the error comes from the code you shared, it seems that chatId is undefined.
You'll want to check in the calling code why that happens. If this is a valid case, you'll want to check for it in sendMessageToFirebase too, for example by adding this to the start of the method:
if (!chatId) return;

Stored procedure azure Cosmos DB returns empty collection

I tried to create a stored procedure using the sample sp creation code from Azure docs, but i couldn't fetch the collection details. It always returns null.
Stored Procedure
// SAMPLE STORED PROCEDURE
function sample(prefix) {
var collection = getContext().getCollection();
console.log(JSON.stringify(collection));
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
var body = { prefix: prefix, feed: feed[0] };
response.setBody(JSON.stringify(body));
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The console shows only this.
the results shows no doc found because of not getting collection.I have passed the partition key at time of execution via explorer.
I had a similar issue. I think the Azure portal doesn't execute stored procedures properly when the partition key is not a string.
In my case I had a partitionKey that is a number. When I executed the stored procedure via the portal I always got an empty resultSet, even though I had documents in my database. When I changed the structure a little, and made my partitionKey a string, the stored procedure worked fine.
Did you create the ToDoList Database with the Items Collection? Yo can do this from the Quick start blade in the Azure portal.
And then create an SP to run against that collection. There is no partition key required, so no additional params are required (leave blank).
The Collection is created without any documents. You may choose to add documents via the Query Explorer blade or via the sample ToDoList App that is available via the Quick start blade.
You are debugging in a wrong way.
It is perfectly fine to see "{\"spatial\":{}}" in your console log, even if the collection has items. Why? well because that is a property of that object.
So regarding what you said:
the results shows no doc found because of not getting collection
is false. I have the same console log text, but I have items in my collection.
I have 2 scenarios for why your stored procedure return no items:
I had the same issue trying on azure portal UI(in browser) and for my surprise I had to insert an item without the KEY in order that my stored procedure to see it.
On code you specify the partition as a string ie. new PartitionKey("/UserId") instead of your object ie. new PartitionKey(stock.UserId)

Get ID of Firebase Pushed Object Is Undefined

Something very strange is happening whenever I try to get the ID of an item I pushed to my Firebase database... I used the code directly from one of their examples:
var fireBaseRef = new Firebase(FIREBASE_ROOT);
var id = fireBaseRef.child("flintstones").push();
id.set({
first: 'Fred',
last: 'Flintstone'
}, function (err) {
if (!err) {
//var name = id.key();
console.log("Set with ID: " + id);
}
});
When this code is run everything works as expected, the Forge portal shows the data was written properly to the database and I get the appropriate javascript console message:
"Set with ID: https://myfirebaseurl.com/flintstones/-JfjdUW4BT32DMgeuAdt"
The problem arises when I uncomment the line
var name = id.key();
As soon as I do that I get a javascript error indicating that no such method exists ("Uncaught TypeError: undefined is not a function."), I don't know what this is happening and I need to use the key value (in this case "-JfjdUW4BT32DMgeuAdt") elsewhere.
Can anyone tell me where I went wrong?
The behavior you see will depend on which version of the client library you are using. Firebase Web / Node.js client libraries < 2.0.0 use FirebaseRef.name(), but that field was renamed in favor of FirebaseRef.key() for v2.0.0 and above. For more information, check out the changelog here.

Parse.com: Find all objects belonging to a user with objectId

I have a Class in parse, say Pictures. Each of these belongs to a user. Reference to this user is stored in the Pictures table/class as a Pointer to the user.
In my cloud code I am trying to get all Pictures belonging to a user, using master key. Following is my code:
Parse.Cloud.define("getPictures", function(request, response) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Pictures");
query.equalTo("user", request.params.user);
query.find({
success: function(results) {
var status = "Found " + results.length + " pictures for userId " + request.params.user;
response.success(status);
},
error: function() {
status = "No pictures exist for userId " + request.params.user;
response.error(status);
}
});
});
This code outputs that there are 0 pictures for a certain user with id 'xyz' for example. However, I can see that the user has a lot of pictures stored.
I have also verified that the problem is not with using master key, as I see in the console log that the code is being executed as master. Moreover, if I query for a picture by objectId, it does come out in the results, which means ACL is not the problem here.
I think I have to use relations/joining here, but I am not sure how to do that.
Pointers are stored as objects in Parse database, so if you try to compare a string to an object with query.equalTo() function, nothing will be found. This is how pointers are stored:
{
__type: 'Pointer',
className: '_User',
objectId: user-object-id
}
If you are querying a class with pointers and want your result comes with the whole object nested, you should set this in your query:
var query = new Parse.Query('Pictures');
query.include('user');
In my queries when I want to search by a pointer column, I compare my user object with the nested user object.
var user = new Parse.User();
// Set your id to desired user object id
user.id = your-user-id;
var query = new Parse.Query('Pictures');
// This include will make your query resut comes with the full object
// instead of just a pointer
query.include('user');
// Now you'll compare your local object to database objects
query.equalTo('user', user);
query.find({
success: function(userPicture) {
response.success(userPicture);
}
});
Anyway, seems that if you have many pictures related to an user, you probably are searching for parse relations instead of pointers: https://www.parse.com/docs/relations_guide
If you write a query to retrieve a parent object and a child object to which you have pointer, but no read access as per ACL, then the query may return only parent object and child will be null because the ACL wont let you read it.
There may be a problem with your params. If "user" is a pointer, then 'request.params.user' is incorrect, because PFObjects may not be sent as params. If "user" is a pointer, use 'request.user'. If request.params.user is a string of the userId, you could use the Id to reconstruct a PFObject shell before the query as was suggested by Murilo already, but deleting the "user" param and using request.user would shorten your code and not duplicate any values. Murilo's solution is also beneficial because you could pass a userId other than the current user's Id.

How do I get the same format for a javascript array and django set on the backend?

I have code that, when a user is logged in, selects recipes that apply to him based on the ingredients (items) he has previously identified identified as possessions.
This code gets the id's of the items the user already has:
if request.user.is_authenticated():
user_items = [possession.item for possession in request.user.possession_set.all()]
user_items_ids = [item.id for item in user_items]
uids = set(user_items_ids)
The following code, which already existed, is where I run into problems...
recipes = [(recipe, len(set([item.id for item in recipe.items.all()]) & uids), recipe.votes) for recipe in recipes]
I created another part of the site that allows people who have not yet signed up to just pick a few ingredients. I do this with some jQuery on the front end, then send the results to the backend:
var ingredient_set = [];
$('.temp_ingredient').each(function(index){
ingredient_set[index] = $(this).attr('id').substr(4);
});
$.get('/recipes/discover', { 'ingredients': ingredient_set },
function(){
alert("Success");
});
The problem is when I receive them on the Django side, with this code:
uids = request.GET['ingredients']
I get the following error:
unsupported operand type(s) for &: 'set' and 'unicode'
Basically, I know they aren't in the same format, but I don't know how to get them to be compatible.
You are sending a JavaScript array in the query string of your GET request. Therefore you should use request.GET.getlist. Just using request.GET[key] gives you the last value for that key.
>> request.GET['foo[]']
u'5'
>> request.GET.getlist('foo[]')
[u'1', u'2', u'4', u'5']
Note that the values are unicode, but you probably need them as integers, so be sure to convert them.
uids = request.GET.getlist('foo[]')
uids = set([int(x) for x in uids])
I'm not sure why my key is actually foo[] and not just foo, but as you get no KeyError, request.GET.getlist('ingredients') should work.

Categories