I am currently experimenting on sequelize.js and more specifically in associations. What i am trying to achieve is the following. I have to models:
user
position
My logic is the following:
A user can or cannot have a position assigned to it
If a user has a position, the id of the position is stored in field "assignedPositionId" of users table.
If a user does not have a position, then "assignedPositionId" value is set to null.
A position can be assigned to more than one users
The issue i am facing is, that i can successfully create a user, but i am unable to create a position! I always keep getting the error message:
SQLITE_ERROR: foreign key mismatch - "positions" referencing "users"
User.hasOne(Position, {
sourceKey: "assignedPositionId",
foreignKey: "id",
as: "position"
});
Position.hasMany(User, {
sourceKey: "id",
foreignKey: "assignedPositionId",
as: "users",
});
I know it's something more than easy - maybe it's late but i really can't figure out what goes wrong! Your help is highly appreciated!
I've had problems using hasOne in these cases, tend to use belongsTo instead, e.g.
User.belongsTo(Position, {
foreignKey: "assignedPositionId",
as: "position"
});
That said, what does the SQL generated look like when you create a Position? Can you execute this directly in the Sqlite shell? That type of error message sometimes suggests a problem with your table PKs.
#KenOn10, thank you for your providing a suggestion. After carefully reading documentation and performing several tests, i ended up with the following approach, which works perfectly:
User.hasMany(Position, {
as: "position",
sourceKey: "assignedPositionId",
foreignKey: "id",
constraints: false
});
Position.belongsTo(User, {
as: "users",
foreignKey: "assignedPositionId",
constraints: false
});
Thank you again for your time.
Related
I have a top level attribute and I want to simultaneously update multiple nested attributes. The params I am passing in are:
{
"TableName":"LOCAL-Table",
"Key":{
"id":"1"
},
"UpdateExpression":"SET #param.#eb321fb16aab1745c55a8659be811f2d = :valeb321fb16aab1745c55a8659be811f2d , #param.#6e3c283fb60480af627ede2758e8e983 = :val6e3c283fb60480af627ede2758e8e983",
"ExpressionAttributeValues":{
":valeb321fb16aab1745c55a8659be811f2d":{
...
},
":val6e3c283fb60480af627ede2758e8e983":{
...
}
},
"ExpressionAttributeNames":{
"#eb321fb16aab1745c55a8659be811f2d":"eb321fb16aab1745c55a8659be811f2d",
"#6e3c283fb60480af627ede2758e8e983":"6e3c283fb60480af627ede2758e8e983",
"#param":"param"
},
"ReturnValues":"UPDATED_NEW"
}
It works when updating a single attribute, but when I put 2 in I get an error stating:
The document path provided in the update expression is invalid for update
Any help greatly appreciated.
Thanks
Actually, this does work, the problem was related to poorly sequenced promises resulting in a race condition.
The Firebase documentation on deleting data says:
Delete data
The simplest way to delete data is to call remove() on a reference to the location of that data.
You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call.
can anybody explain to me what they mean by the last line I think is could help me delete all files in a firebase folder?
In Firebase:
dataRef.remove() is strictly equivalent to dataRef.set(null)
dataRef.child('foo').remove() is strictly equivalent to dataRef.update({ foo: null })
That means that setting or updating to null will effectively remove the property.
Updates can be used for removing multiple properties in that way:
Consider this example Firebase Object:
exampleData = {
foo: 'anyValue',
bar: 'otherValue',
baz: {
aProp: true,
anotherProp: false
}
}
The following
db.ref('/exampleData').update( { bar: null, 'baz/aProp': null })
will result in the following object:
exampleData = {
foo: 'anyValue',
baz: {
anotherProp: false
}
}
So you can use one update instead of multiple remove (or set) to delete several properties.
If you have this in your database:
users: {
user9266622: {
id: 9266622,
name: "SylvainC"
},
user209103: {
id: 209103,
name: "Frank van Puffelen"
}
}
Then you can delete a specific property with something like:
firebase.database().ref("/users/user209103/name").remove();
You can remove an entire branch by calling remove() on the top of that branch. So to remove "my" entire profile:
firebase.database().ref("/users/user209103").remove();
I think this last snippet is what you're looking for: it removes /users/user209103 and everything under it.
The last line of the documentation you quote is about updating/removing multiple branches/properties in distinct locations in one call. For example, say you want to remove the id property from both profiles (since they're redundant). You can do this with:
firebase.database().ref().update({
"/users/user9266622/id": null,
"/users/user209103/id": null
});
This is called a multi-location update, since you're updating two locations by their full path.
Trying to make use of Azure DocumentDB/CosmsoDB using the MongoDB driver. I have learned that there are many limitations as the full set of features is not currently implemented. I want to use aggregate functions, specifically $group, and .distinct but I don't think that is available yet. As a work around, I am trying to maintain a separate "tracking" document to enable "distinct". trying to update a document using $addToSet, but getting the following:
MongoError: Message: {"Errors":["Encountered exception while executing function. Exception = Error: AddToSet operation requires a target array field.\r\nStack trace: Error: AddToSet operation requires a target array field.\n at arrayAddToSet (__.sys.commonUpdate.js:2907:25)\n at handleUpdate (__.sys.commonUpdate.js:2649:29)\n at processOneResult (__.sys.commonUpdate.js:2484:25)\n at queryCallback (__.sys.commonUpdate.js:2461:21)\n at Anonymous function (__.sys.commonUpdate.js:619:29)"]}
The update command i am using:
var usersDocument = collection.updateOne(
{ "type": "users" },
{ $addToSet: {users: "someone#gmail.com"} },
function(err, count, status) {
console.log("updateOne err: " + err)
console.log("updateOne count: " + count)
console.log("updateOne status: " + status)
}
)
This seems to me to be a pretty straight-forward command, pulled from the mongo documentation and fields adjusted as needed. Maybe I am missing something really basic?
My ultimate goal was to make sure that my code was portable as to be able to move it into a Mongo cluster, if I so desired (not be locked into Azure-specific). To get started and not have to manage a multi-server cluster, Azure CosmosDB looked like a great jumpstart, but the limitations are maddening.
UPDATE:
Now that I have fixed my document and I actually have a field with an array, $addToSet is just replacing the value, rather than adding to the array. I'll create a new question for that.
Yup, something basic. The error message was actually correct. After inspecting the existing document:
I found:
{ "users": "[]" }
And changed it to:
{ "users": [] }
Now it is working.
I have three models, User, Project and ProjectMember. Keeping things simple, the models have the following attributes:
User
- id
Project
- id
- owner_id
- is_published
ProjectMember
- user_id
- project_id
Using sequelize.js, I want to find all projects where the project owner is a specific user, or where there is a project member for that project whose user is that user, or where the project is published. I imagine the raw SQL would look something like this:
SELECT p.*
FROM Project p
LEFT OUTER JOIN ProjectMember m
ON p.id = m.project_id
WHERE m.user_id = 2
OR p.owner_id = 2
OR p.is_published = true;
There are plenty of examples out there on how to perform a query on an association, but I can find none on how to do so conditionally. I have been able to query just the association using this code:
projModel.findAll({
where: { },
include: [{
model: memberModel,
as: 'projectMembers',
where: { 'user_id': 2 }
}]
})
How do I combine this where query in an $or to check the project's owner_id and is_published columns?
It's frustrating, I worked for hours to try to solve this problem, and as soon as I ask here I found a way to do it. As it turns out, sequelize.js developers recently added the ability to use raw keys in your where query, making it (at long last) possible to query an association inside of the main where clause.
This is my solution:
projModel.findAll({
where: {
$or: {
'$projectMembers.user_id$': 2,
owner_id: 2,
is_published: true
}
},
include: [{
model: memberModel,
as: 'projectMembers'
}]
})
Note: this solution breaks if you use 'limit' in the find options. As an alternative, you can fetch all results and then manually limit them afterwards.
The current query you see below is not efficient because I have not setup the proper indexing. I get the suggestion Consider adding ".indexOn": "users/kxSWLGDxpYgNQNFd3Q5WdoC9XFk2" at /conversations in the console in Xcode. I have tried it an it works.
However, I need the user id after users/ to be dynamic. I've added a link to another post below that has tried a similar thing, but I just can't seem to get it. All help would be much appreciated!
Note: The console output user id above does not match the screenshot below, but does not matter to solve the problem I believe. Correct me if I'm wrong. Thanks!
Here is the structure of my DB in Firebase:
{
"conversationsMessagesID" : "-KS3Y9dMLXfs3FE4nlm7",
"date" : "2016-10-19 15:45:32 PDT",
"dateAsDouble" : 4.6601793282986E8,
"displayNames" : [ “Tester 1”, “Tester 2” ],
"hideForUsers" : [ "SjZLsTGckoc7ZsyGV3mmwc022J93" ],
"readByUsers" : [ "mcOK5wVZoZYlFZZICXWYr3H81az2", "SjZLsTGckoc7ZsyGV3mmwc022J93" ],
"users" : {
"SjZLsTGckoc7ZsyGV3mmwc022J93" : true,
"mcOK5wVZoZYlFZZICXWYr3H81az2" : true
}
}
and the Swift query:
FIRDatabase.database().reference().child("conversations")
.queryOrderedByChild("users/\(AppState.sharedInstance.uid!)").queryEqualToValue(true)
Links to other post:
How to write .indexOn for dynamic keys in firebase?
It seems fairly simple to add the requested index:
{
"rules": {
"users": {
".indexOn": ["kxSWLGDxpYgNQNFd3Q5WdoC9XFk2", "SjZLsTGckoc7ZsyGV3mmwc022J93", "mcOK5wVZoZYlFZZICXWYr3H81az2"]
}
}
}
More likely your concern is that it's not feasible to add these indexes manually, since you're generating the user IDs in your code.
Unfortunately there is no API to generate indexes.
Instead you'll need to model your data differently to allow the query that you want to do. In this case, you want to retrieve the conversations for a specific user. So you'll need to store the conversations for each specific user:
conversationsByUser {
"SjZLsTGckoc7ZsyGV3mmwc022J93": {
"-KS3Y9dMLXfs3FE4nlm7": true
},
"mcOK5wVZoZYlFZZICXWYr3H81az2": {
"-KS3Y9dMLXfs3FE4nlm7": true
}
}
It may at first seem inefficient to store this data multiple times, but it is very common when using NoSQL databases. And is really no different than if the database would auto-generate the indexes for you, except that you have to write the code to update the indexes yourself.