Schema for Document with changeable user id - mongodb

I get such data (lets call it event) from many machines and I want to put them into mongodb:
`event`
{
"payload":"xxxxxxxxxxxx",
"user":{
"user_sid":"S-1-5-21-2242820312-3698568055-2602798999-1000",
"user_login":"john1"
}
}
later, this user could change his machine and new id will be generated for him - user_sid
new entry with new user_sid
`event`
{
"payload":"xxxxxxxxxxxx",
"user":{
"user_sid":"S-1-5-21-2242820312-3698568055-2602798999-5555",
"user_login":"john1"
}
}
So, all historical data after change cannot be associated in queries with new ones.
I have two ideas to handle this:
First is to make collection.users for holding user_sids and link user._id to event collection.
When new event with new user_sid come, new user will be added and
new event will be linked with new user_sid.
Then, application user will be able to recognize john1 has change user_sid and could merge these users.
Old user.user_sid will be replaced with new one so old _id references in historical data need no change, new event will get _id
with updated Old user.user_sid and new user.user_sid will be
deleted.
Second is to make collection.users for holding user_sids but no referencing it in event. collection.users will hold every new user_sid for particular user and in queries put all user_sid for that user
Because I`am just starting with NoSQL I need advise with one is better?

I think you can just add a user _id to the event document:
{
"payload" : "xxxxx",
"user" : {
"user_sid" : "9rjvq835hgq0845uhr",
"_id" : 1231231231,
"user_login" : "john1"
}
}
The path to the user_sid field is user.user_sid. I think it's better just to call it sid since the association with a user is obvious from the embedding and doesn't need to be repeated in the name.

Related

Get parent nodes from Firebase realtime database event in flutter application

In my flutter application, I'd like to keep track of the employee location for different companies without having to flatten the database (see architecture below).
Q1 : If I set a listener on an office node, is there a way to get the parents nodes from the event ?
Q2 : if a new company node is created in the database, how can I attach dynamically a new listener on the office's new company ?
_employeesQuery = databaseReference.reference().child("Company_1/Office_1");
_onEmployeeAddedSubscription =
_employeesQuery.onChildAdded.listen(onEmployeeAdded);
...
onEmployeeAdded(Event event) {
setState(() {
String name = event.snapshot.key;
print("New employee added $name in Office ?? in Company ??");
});
}
Firebase's documentation recommends to avoid nesting data and flatten data structure for a good reason. You are not following that advice here, and that's the reason for the mismatch between your data structure and the use-case.
Firebase child listeners work on a flat list of child nodes, they have no knowledge of a hierarchy. So in your model you can listen to all offices, and then get a childChanged when something in an office changes, or you can listen to a specific office, and then get a childAdded when a user is added to that office. If you listen to all offices, you'll have to figure out what changed yourself in your application code.
Following Firebase recommendations, I'd actually model your data as two top-level lists:
userOffices: {
"Dan": "Company_1/Office_1",
"Tom": "Company_1/Office_1",
"Pete": "Company_1/Office_2",
"max": "Company_1/Office_2"
},
officeUsers: {
"Company_1-Office_1": {
"Dan": true,
"Tom": true
},
"Company_1-Office_2": {
"Pete": true,
"max": true
}
}
The exact model might be a bit different, but the important thing here is that we've stored he data in both directions. You can now fine the users for an office, and the office for a user with a direct lookup. And you can listen to userOffices to know when a user is added to any office.
Also see:
Many to Many relationship in Firebase
Firebase query if child of child contains a value

Creating new docs without auto-ids without accidentally referencing an existing doc

If I have a collections of docs in which I provide the ids (i.e. not the Firestore auto ids), how can I be certain to create a new doc rather than referencing an existing one?
For instance if I have a collection foo with a document id bar, I can reference it as (given db is the injected AngularFirestore service) this.db.doc('foo/bar').
Then later I want to create another foo doc, I can check if it already exists with something like
checkExits(id: string): Observable<boolean> {
const docRef = this.db.doc(`foo/${id}`);
return docRef.snapshotChanges().map(change => change.payload.exists);
}
However in the time that I check that it exists, to creating the doc, isn't it possible that it gets created? Such that when I try to create the new doc, it is instead referencing an existing one and overwriting it? i.e. this.db.doc('foo/bar').set({})
How can I create new docs specifying the id, while avoiding referencing existing docs (and throwing an error if it exists).
You'll want to use a transaction for that. Within the transaction you first call get() on the location, to ensure nothing exists yet. Then you write to the same location, to create the document.

Get Mongoose to automatically create joined document

I have 2 Mongoose.js Schemas that work together with the 'populate' feature: A 'user' schema and another based on their role. E.g. 'admin'. When a user is assigned a role, a corresponding document needs to be created in a different collection with a link to the _id of the document in the users collection. (Yes, more like an SQL database than non-relational, I know)
Currently I manually create the second document in my code whenever a user with a specialized role is created or a role is added to a user. |
I'd like to know if there is a way to automatically create this corresponding record from my schema whenever a 'user' document is created or updated with a role.
Any advice?
Nothing will do it automatically, but you can use the mongoose middleware to insert our update a document in another collection pre or post save.
The post hook will have the _id populated.
If you want to do it in the pre hook (to enforce some transactional integrity) you can assign the _id manually.

History in database using entity framework

I want to store history in my table.
I have table Employee.
Employee
{
[Id],
[name],
[phone],
[isActive],
[createdDate],
[closedDate](default '23:59:59 9999-12-31'),
[DepartmentId] References Department(id)
}
When Employee is changed, I retrieve original values by Id and do isActive=False, closedDate=DateTime.Now and then I save modified value as new Employee with modified original values.
void UpdateEmployee(Employee employee)
{
ContextDB db=new ContextDB();
var employeeToUpdate=db.Employees.Find(it=>it.Id==employee.Id);
employeeToUpdate.isActive=false;
employeeToUpdate.closeDate=DateTime.Now;
var newEmployee=new Employee
{
Name=employee.Name,
Phone=employee.Phone,
....
}
db.Employees.AddObject(newEmployee);
// How I can do this with EF
db.Employees.Modify(employeeToUpdate);
db.SaveChanges();
}
How can I do this? And another question, what I need do if I have reference to another table Department and also want store history in this table. How should I do if changes Department in Employee object.
P.S. I use Self-Tracking Entities.
It should simply work without calling any Modify. You loaded entity from the database and you modified its fields while it is attached to the context so the context should know about changes and persist them to the database.
What I find totally bad about your architecture is that each change to your employee will result in active record with another Id. So if you are using and relation with employee table, foreign keys will not point to active record any more. If you want to do it this way you should not create a new record for active record but you should instead create a new record for deactivated record.

Removing an association from an entity

I have 2 entities: User and Company, with a FK from the User to the Company.
I'm trying to remove the association and leave the user entity with a scalar property "CompanyId", but still have the "Company" entity in the model (mainly to increase performance, I don't need to full entity attached to it).
I'm able to achieve that only by removing the association and then go to the edmx (xml) file and remove the leftovers manually, BUT...
After I regenerate the model (following additional changes in the schema etc.), I'm getting the "Company" association once again on the "User" object (along with the "CompanyId" property), which of course causes errors of mappings, since I'm having 2 mappings to the same CompanyId field in the database. Going once again to the xml to fix it is not something I'd like to do...
Is there a way around this? -Taking the "Company" table out to another model is not possible.
Thanks,
Nir.
I think I found the answer.
I can leave the entity association without the scalar property, and set it to a private getter. Then, add to the partial class the following:
public int CompanyId
{
get
{
return
(int)CompanyReference.EntityKey.EntityKeyValues.First(c => c.Key == "Id").Value;
}
}
That way I don't need to go to the database to fetch the company association along with the user, but I still have the value.
Nir.