Cloud firestore - adding object to an array of objects - node.js

I am using Cloud Firestore (not Realtime Database). I have a document of user details containing an array (cards) of user credit cards, i.e. Card objects. A card object is structured as follows:
{
address: "123"
number: "456643634634634"
postcode: "hshshs"
}
The document is defined as follows:
userDocument : AngularFirestoreDocument<User>;
this.userDocument = this.afs.collection('users').doc(`${this.userId}`);
When a user adds a new card, I call the following function:
addCard(card: Card){
this.userDocument.update({
cards : firebase.firestore.FieldValue.arrayUnion(card)
});
}
However, I get errors before even saving the document saying:
[ts]
Type 'FieldValue' is not assignable to type 'Card[]'.
Property 'length' is missing in type 'FieldValue'. [2322]
user.model.ts(15, 5): The expected type comes from property 'cards' which is declared here on type 'Partial<User>'
Not sure how to use arrayUnion to add an element to an array in Cloud Firestore correctly. Can anyone help with this?

Related

Google Datastore can't update an entity

I'm having issues retrieving an entity from Google Datastore. Here's my code:
async function pushTaskIdToCurrentSession(taskId){
console.log(`Attempting to add ${taskId} to current Session: ${cloudDataStoreCurrentSession}`);
const transaction = datastore.transaction();
const taskKey = datastore.key(['Session', cloudDataStoreCurrentSession]);
try {
await transaction.run();
const [task] = await transaction.get(taskKey);
let sessionTasks = task.session_tasks;
sessionTasks.push(taskId);
task.session_tasks = sessionTasks;
transaction.save({
key: taskKey,
data: task,
});
transaction.commit();
console.log(`Task ${taskId} added to current Session successfully.`);
} catch (err) {
console.error('ERROR:', err);
transaction.rollback();
}
}
taskId is a string id of another entity that I want to store in an array of a property called session_tasks.
But it doesn't get that far. After this line:
const [task] = await transaction.get(taskKey);
The error is that task is undefined:
ERROR: TypeError: Cannot read property 'session_tasks' of undefined
at pushTaskIdToCurrentSession
Anything immediately obvious from this code?
UPDATE:
Using this instead:
const task = await transaction.get(taskKey).catch(console.error);
Gets me a task object, but it seems to be creating a new entity on the datastore:
I also get this error:
(node:19936) UnhandledPromiseRejectionWarning: Error: Unsupported field value, undefined, was provided.
at Object.encodeValue (/Users/.../node_modules/#google-cloud/datastore/build/src/entity.js:387:15)
This suggests the array is unsupported?
The issue here is that Datastore supports two kinds of IDs.
IDs that start with name= are custom IDs. And they are treated as strings
IDs that start with id= are numeric auto-generated IDs and are treated as integers
When you tried to updated the value in the Datastore, the cloudDataStoreCurrentSession was treated as a string. Since Datastore couldn't find an already created entity key with that custom name, it created it and added name= to specify that it is a custom name. So you have to pass cloudDataStoreCurrentSession as integer to save the data properly.
If I understand correctly, you are trying to load an Array List of Strings from Datastore, using a specific Entity Kind and Entity Key. Then you add one more Task and updated the value of the Datastore for the specific Entity Kind and Entity Key.
I have create the same case scenario as yours and done a little bit of coding myself. In this GitHub code you will find my example that does the following:
Goes to Datastore Entity Kind Session.
Retrieves all the data from Entity Key id=5639456635748352 (e.g.).
Get's the Array List from key: session_tasks.
Adds the new task that passed from the function's arguments.
Performs the transaction to Datastore and updates the values.
All steps are logged in the code and there are a lot of comments explaining exactly how the code works. Also there are two examples of currentSessionID. One for custom names and other one for automatically generated IDs. You can test the code to understand the usage of it and modify it according to your needs.

How to autogenerate id if there is no id in document with elasticjs v5.0

I am trying to add documents, according to elastic search documents, we can add document, even if we dont provide id... See Here
I am trying to add a document even if it doesnt have any ID. in elastic search, how can i do that?
My current code looks like this
var params = _.defaults({}, {
index: index,
type: type, //'customer'
id: data.id || null,
body: data
})
debug(params)
return this.client.create(params);
The above code gives this error
{
"error": "Unable to build a path with those params. Supply at least index, type, id"
}
Any hint would help, thanks
With the create call you MUST provide an id.
If you are not sure if an ID will be present in your data , then you can use the client.index() function instead. using that function, ES will auto-generate an ID if none is provided.

how to use the attribute type like 'array' and 'json' in sails

Sails have support very convenient model througth Waterline, and I have used the 'array' attribute type in the way storing many string, but now I want to store more complex object, Although I can store the raw data in mongo by 'array' type, I don't know if it is safe and I want define the object type in the array, like mongoose's style. for example, I need a model "Products" and I want define it as a 'array' but the object stored in the array only model "Book", what I can do like this, but I don't think it works.
module.exports = {
products : {
type : 'array',
Book : {
name : 'string',
price : 'integer'
}
}
}
So, any suggestion about use of the 'array' and 'json' is very appreciated, thanks so much!
I don't think that the array type is going to work the way you want it to. What you're looking for is associations which will be available in SailsJS 0.10 (which you can get via git right now). The array attribute type for MySQL and PostgreSQL it will only stringify the array and store it as text in the database then it will parse the field when returning the value.
source

Mongoose - Is it possible to access object properties with schema path?

As title. There's an object property vote under ActionSchema. I want to access vote.type, but path('vote.type') doesn't work.
ActionSchema = new Schema({
vote: {
type: String
}
});
// TypeError: Cannot call method 'enum' of undefined
ActionSchema.path('vote.type').enum(['upvote', 'downvote']);
The issue is that vote.type isn't the path, vote is. So if you want to modify the vote property, then you want to use ActionSchema.path('vote')
So to add an enum:
ActionSchema.path('vote').enum('upvote', 'downvote');
* Note that you don't pass an array of enum values to this function, you pass the values in as multiple arguments. See the Mongoose documentation for more details.

Programming with node.js and mongoose. Error id want to pass the value to update registration

I'm learning to use with mongoose and node.js when editing to generate a content that gives me the error: 500 TypeError: Can not read property 'ObjectID' of undefined. Check whether the parameter that I send comes empty and is not.
Remove the option and gives me that error when saving the data did not find the method I use to save some registry update.
If I can help as I have code in https://github.com/boneyking/PruebaNode.git
First of all, please provide code or at least a link to the code. A link to your github repo is not cool !!!
Now back to the question... Add an id to your model and get it like other types:
var SUPER = mongoose.model('Producto',{
nombre: String,
descripcion: String,
precio: Number,
id: mongoose.Schema.Types.ObjectId
});
SUPER.editar = function(newData, callback){
SUPER.findOne({id: newData.id}, function(e,o){
o.nombre = newData.nombre;
o.descripcion = newData.descripcion;
o.precio = newData.precio;
SUPER.save(o);
callback(o);
});
}

Resources