Firestore: set post id - google-cloud-firestore

How can I set id of post that I'm adding? I thought that getItemNextKey() returns id that will be assigned for the post, but it's not.
AddItem(data, downloadURLs) {
data.id= this.getItemNextKey(); // Persist a document id
data.upload = downloadURLs;
// console.log('this.uploadService.downloadURLs: ' + downloadURLs);
// console.log('data.upload: ' + data.upload);
this.db.collection('items').add(data);
}

I did this and it works now.
// Add a new document with a generated id
var addDoc = this.db.collection('items').add(data).then(ref => {
var updateNested = this.db.collection('items').doc(ref.id).update({
id: ref.id
});
});

As stated in the official docs
When you use set() to create a document, you must specify an ID for
the document to create. For example:
db.collection("cities").doc("new-city-id").set(data);
If you dont want to set an ID yourself you can use add
But sometimes there isn't a meaningful ID for the document, and it's
more convenient to let Cloud Firestore auto-generate an ID for you.
You can do this by calling add():

Related

How can I create a relation in Strapi if I don't know the id of the field?

I am creating a collection of judges and courthouses. Every judge will be assigned to one courthouse. I have set up my relation to be that courthouse has many judges
I am attempting to do this programmatically when the app loads. I have a function that is able to populate all the fields in judge except the relation to courthouse. My function uses the Strapi API like this
const judge = await strapi.query('judge').create({
name: data[i].name,
},
{
courthouse: data[i].courthouse_name // here is where I think the relation is created
}
)
I am passing in a string that has the name of courthouse, because I don't know the ID of the courthouse in the Courthouse collection.
My question is it possible to create a relation to another collection by anything other than an ID? How can I create a relation to a courthouse by its name?
I couldn't find a way around building a relationship between two models without the ID, so I created a custom solution using the Strapi lifecycle hooks
Essentially what I did I utilized the beforeCreate lifecycle hook to query and find the courthouse that matches the name like this:
// judges.js
async beforeCreate(result, data) {
const courthouse = await strapi.query('courthouse').find(
{courthouse_name:data.courthouse}
); // returns the courthouse that matches the name
result['courthouse'] = courthouse[0].id; // populates the relational field with the
// ID of the courthouse
}
The response object contained the courthouse's ID and I manipulated the data that is being sent to the create command like this:
const judge = await strapi.query('judge').create({
name: data[i].name,
courthouse: data[i].courthouse_name
})
The result is an object that looks like this:
{name: 'Garfield Lucas, courthouse: 7463987}

using email addresses as keys in firestore

I want to create "invitations" based on email addresses so that when a user with that email would arrive to the system his invitations would already be waiting for him.
so I wanted to create an invitations collection with key based on groupId + '_' + invited_user_email but if the user is test#test.com this the .com is interpreted as a subkey :(
I tried groupId + '_' + invited_user_email.replace(/[.]/g,'\\.') but it did not help either.
What am I missing? Is there no way to include a '.' in a firestore document's ID ?
EDIT:
per Doug Stevenson's request here is the code I use now:
var invitedUserEmailAsKey=invitedUserEmail.replace(/[.]/g,'\\.')
var batch = db.batch();
var groupRef = db.collection("groups").doc(groupId);
var invitationRef = db.collection("invitations").doc( groupRef.id + '_' + invitedUserEmailAsKey);
var groupUpdates = {};
groupUpdates['invited.' + invitedUserEmailAsKey + '.user_name'] = invitedUserName;
groupUpdates['merge'] = true;
batch.update(groupRef, groupUpdates);
The problems are with the updated document on the groups collection.
It ends up looking like this:
instead of having someone#gmail.com as a key
Using update() with "dot" in a key is interpreted as a nested field as documented here.
Notice that you're updating a document fields (groupRef) and not really doing anything with the "invitations" collection. I don't think that creating a new field on the group doc for every invitation is what you really mean to do.
As Dror mentioned, adding users with update() and a dot in the key won't work.
I use the set method with merge true:
addUserToGroup(id,email,type){
this.log("id",id,"email",email,"type",type);
let obj = {};
obj[email] = type;
this.angularFireStore.collection("Users").doc(id).set(obj, { merge: true }).then(() => {
this.log("addedUser",email);
}).catch((error) => {
this.log("failed to add user",error)
})
}
From the documentation: https://firebase.google.com/docs/firestore/manage-data/add-data#web-v8_1
"To create or overwrite a single document, use the set() method"
"If you're not sure whether the document exists, pass the option to merge the new data with any existing document to avoid overwriting entire documents."

Backbonejs Model.url required?

I have an example setup to show my issue: http://jsfiddle.net/5xo4yzw2/1/
var root = "http://jsonplaceholder.typicode.com"
var Post = Backbone.Model.extend({
url: function(){
return this.get('url') || root + "/posts/" + this.get('id')
}
});
var Posts = Backbone.Collection.extend({
model: Post,
url: root + "/posts"
});
var posts = new Posts();
posts.fetch();
console.log("Call to collection fetch works")
var post = new Post({id: 1});
post.fetch();
console.log("Call to collection fetch works")
This example works, that is, both of the console.logs are executed without an exception being raised by .fetch(). It was my understanding, however, from both http://backbonejs.org/#Model-url and the book I am reading, that once I specify "/posts" as the collection url, the model url should be automatically resolved to [collection.url]/[id], though that is not the case. If I do not provide the url function in the model, an exception is raises upon fetching, stating the th url parameter must be provided.
Have i misunderstood something?
You haven't added your post model to your collection, in order for a model to use the collections URL it must be part of that collection.
For example
var post = new Post({id: 1});
posts.add(post);
post.fetch();
console.log("Call to collection fetch works")
Updated Fiddle
As #Artem Baranovskii pointed out, If you want to use a model outside a collection you should be using the urlRoot property. From the documentation
Specify a urlRoot if you're using a model outside of a collection, to
enable the default url function to generate URLs based on the model
id. "[urlRoot]/id" Normally, you won't need to define this. Note that
urlRoot may also be a function.
If you're using a model outside of the collection you could use urlRoot like the following:
var root = "http://jsonplaceholder.typicode.com"
var Posts = Backbone.Model.extend({
urlRoot: function () {
return this.get('url') || (root + "/posts/" + this.get('id'))
}
});
var posts = new Posts();
posts.fetch();
console.log("Call to collection fetch works")
When you execute fetch the model tries to get url by the several approaches here

Crossreference two collections

I have two collections A + B. Both are created at the same event. B is created some lines before A. Now I need to store in A the _id of B. How do I get the id of the just created B?
I am new to meteor and mongoDB, is the _id internally passed back on creation so that it is already available (I did not find an indication for this) or do I need to reread B? If so how do I do this best?
EDIT
I understand that the _id is passed back on the server after the insert.
Client:
Meteor.call('addB',b );
Server:
'addB':function(b){
return B.insert(b);
},
How can I pass B._id to the client so that I can do, on the client, something like:
a.id_of_B = B._id
Meteor.call('addA',a );
collection.insert returns the value of the created _id field. The docs says "Returns its unique _id.".
To return the values to the client a simple callback can be used:
Here again the link to the docs collection.insert
Client:
Meteor.call('addB',b function(error, result) {
BId = result;
});
Server:
'addB':function(b){
return B.insert(b);
},
Remember that in general you don't need Meteor.call() to insert into a collection. You can do both inserts on the client (if the collections are available there) and these inserts will automatically be synchronized back to the server.
var a = {...}; // some object
var b = {...}; // some other object
B.insert(b,function(err,id){ // asynchronous style
a.idOfB = id;
A.insert(a);
})
a.idOfB = B.insert(b); // synchronous style
A.insert(a);

Node + Mongoose: Get last inserted ID?

I want to retrieve the last inserted _id, using mongoose as MongoDB wrapper for node.js. I've found the following tutorial, but I can't change any node modules because the app runs on a public server:
Getting "Last Inserted ID" (hint - you have to hack Mongoose)
Any other ideas? This what I want to do:
Insert new user
Get user's _id value
Set a new session based on user's id
Redirect to /
Thanks!
I'm using mongoose version 1.2.0 and as soon as I created a new instance of a mongoose model, the _id is already set.
coffee> u = new User()
[object Object]
coffee> u._id
4dd68fc449aaedd177000001
I also verified that after I call u.save() the _id remains the same. I verified via MongoHub that this is indeed the real ID saved into MongoDB.
If you explicitly declare
_id: Schema.ObjectId
for your model, then the ObjectId will not be available after new or save.
This is probably a bug.
If you're looking to get the last inserted _id of a sub object, then create the object, and add it to the item. Here's an example in NowJS using MongoDB and Mongoose (to add some schema sugar) which then converts the result to JSON to send back to the client:
var nowRoomID = this.now.room;
var Conversation = mongoose.model('Conversation');
Conversation.findById(convID, function(error, conversation) {
var Blip = mongoose.model('Blip');
var createdBlip = new Blip();
createdBlip.author= nowUserName;
createdBlip.authorid = parsed.authorid;
createdBlip.body = revisedText;
createdBlip.created_at = new Date();
createdBlip.modified_at = new Date();
conversation.blips.push(createdBlip);
parsed._id = createdBlip._id; //NOTE: ID ACCESSED HERE
message = JSON.stringify(parsed);
conversation.save(function (err) {
if (!err) {
console.log('Success - saved a blip onto a conversation!');
nowjs.getGroup(nowRoomID).now.receiveMessage(nowUserName, message);
}
});
With MongoDB, if you don't explicitly set a document's _id value then the client driver will automatically set it to an ObjectId value. This is different from databases that might generate IDs on the server and need another query to retrieve it, like with SQL Server's scope_identity() or MySQL's last_insert_id().
This allows you to insert data asynchronously because don't need to wait for the server to return an _id value before you continue.
So, as shown is Peter's answer, the _id is available before the document is saved to the database.
I just get the id from the document passed to the callback, since save returns the saved document.
Check below url
http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
you will find following code in given url
var document = {name:"David", title:"About MongoDB"};
collection.insert(document, {w: 1}, function(err, records){
console.log("Record added as "+records[0]._id);
});