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.
Related
I am working on an app the will inject docs in to firestore database those docs will have an id generated by uuid v4 the question is could 2 user every user on a different browser created same doc with the same id ? since the uuid function is the same ? if a duplicated could occur it will overwrite someone's data! in case if uuid is generation the ids not by timestamp.
other wise 2 users will have same reference which also really bad case ! could npm uuid be used for this purpose ?
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();
If you want to get the ID of a document you're adding to Firestore before the document is actually added, have a look at this section of the Firebase documentation on adding a document:
In some cases, it can be useful to create a document reference with an auto-generated ID, then use the reference later. For this use case, you can call doc():
import { collection, doc, setDoc } from "firebase/firestore";
// Add a new document with a generated id
const newCityRef = doc(collection(db, "cities"));
// later...
await setDoc(newCityRef, data);
This is the JavaScript code for v9 or later of the SDK. Code for other languages can be found at the link above.
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.
As you may know that whenever we set a new database inside "sails-orientdb adapter" configurations it creates database, now on the creation time of the database of course database will be created if there is no database inside orientdb with this name, now I want to create vertices related to a class you can say those vertices are defaults of my application, whenever new database will be created those defaults will also be created, but when database already exists those defaults will also be skipped.
Now, is there any function like exists() available inside Waterline or Oriento which can check that database with the specified name inside configurations exists or not inside orientdb and return true or false?
There is not a function .exists() but Oriento has a function named .list() which will list all DBs and allows checking if a particular DB is present. To do this from Sails-OrientDB you can use the custom method .getServer() as follows:
// Assume a model named "Post"
Post.getServer()
.list()
.then(function (dbs) {
var dbExists = _.find(dbs, function(db) {
return db.name === 'myDatabaseName';
});
console.log('myDatabaseName exists:', dbExists);
});
This is the logic that Sails-OrientDB uses to determine if the DB exists before creating it: https://github.com/appscot/sails-orientdb/blob/master/lib/connection.js#L604-L608
What is the best practise for updating a single field for one record (with specific ID) using ADO.Entity?
As far as I know, you have to retrieve the whole object by id, update the property and call SaveChanges:
int id = ...;
var db = new MyEntities();
var o = (from mo in db.myObject
where mo.id = idObject
select mo).First();
o.MyProperty = "some value";
db.SaveChanges();
But it seems a little bit overhead having to retrieve the whole object, since I don't care for the values of the record because I just want to set a property, regardless of the values.
Another option would be to create a stored procedure for this purpose...
Re: What is the best practise for updating a single field for one record (with specific ID) using ADO.Entity?
Answer: Best practice is to retrieve the entire record, update one or more fields, and then store the record. -- Just as you're doing.
What is the right way to delete all of the collection items of an EF entity? In the code below, DocumentItems is the collection of related document items for a document. This code proceedes on Clear() but fails on SaveChanges() because related items are connected to their document via FK and FK is mandatory. So I guess they somehow remain floating up in the air without a foreign key after Clear().
Do I solve this with a foreach loop over the collection calling Remove() on each item or is there another way?
// remove existing document items to prepare for refreshing them
existing.DocumentItems.Clear();
// adds new Document Items
PrepareInvoice(existing, collection);
_repository.SaveChanges();
This is one way of deleting the items in the collection.
VB
TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
C#
TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
Then you need to call
ctx.SaveChanges()
Clear just removes the reference but doesn't delete the entity.
In your situation
existing.DocumentItems.Clear();
All DocumentItems in the EntitySet will get cleared but you will have to Remove/Delete the actual DocumentItem or the commit with fail, just the same as it would if you tried to delete it in the database.
You need to loop through detach any references, and then delete the entity you wish to remove (unless its nullable and in your situation, it is not)
Alternatively, I have seen implementations that use clear, and an AssociationChangedHandler to automatically delete the old object. Basically, if the change is a "delete/remove" it calls DeleteObject() on the orphaned object.
Trick: When setting up the relationship between Parent and Child, you'll HAVE TO create a "composite" key on the child. This way, when you tell the Parent to delete 1 or all of its children, the related records will actually be deleted from the database.
To configure composite key using Fluent API:
modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });
Then, to delete the related children:
var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);
var childToRemove = parent.Children.First(); // Change the logic
parent.Children.Remove(childToRemove);
// or, you can delete all children
// parent.Children.Clear();
_context.SaveChanges();
Done!
Yeah, a year old, but on a minor note... since DeleteObject takes one parameter, which is the same type as the argument for the lambda expression, you can just use:
entityCollection.ToList().ForEach(ctx.DeleteObject);
I am not sure if VB supports a similar syntax, though. Anyone?
Just to answer to Nix comment to the answer,
it seems to me that the EntityCollection.Remove() method only marks for deletion the relationships and not the entities, just as the EntityCollection.Clear() method does.
I know that documentation says that also the entity will be marked for deletion but in my test I've got the behavior I described (anyone can explain me why?).
So, if you have a one to many foreign key constraint in your conceptual model, you cannot save the changes to the context in the persistence store.
The only way I found (since I don't want to CascadeDelete) is looping through the children and invoke context.DeleteObject on each of them, thus removing the entity and the associated relationship.