Integromat automation problem - can't store an array in Google Firestore - google-cloud-firestore

Overview - I'm trying to sync some data to google firestore using Integromat. However I cannot seem to find the correct way to save an array as the output for a particular field. It seems like this should be easy but everything I've tried has failed so far.
Example, using the simplest form of this I have an input string like so
Input JSON:
{ "Brand": "Ford", "widgets": [0,1,2] }
And I basically just want to save that in the same structure into firebase, but I can't seem to configure the 'Update Firestore Document' module correctly. The closest I can do is to save it as a string, so it looks like this in firebase:
Output Firestore: { "Brand": "Ford", "widgets": "0,1,2" }
Below I'm attaching images of the integromat setup, showing how I'm trying to hookup the output values into the firestore module. When I try and pass the array directly I get the error message. "Array of objects expected in the parameter 'Value'"

I have reviewed your integration and one thing that needs to be fixed is the way you are passing the Array of Values in Google Cloud FireStore through Integromat. When reviewing the API the expected format for FireStore looks something like this,
{
"fields": {
"widgets": {
"arrayValue": {
"values": [
{
"integerValue": 0
},
{
"integerValue": 1
},
{
"integerValue": 2
}
]
}
},
"brand": {
"stringValue": "Ford"
}
}
}
But, Since the app is developed in Integromat there are few changes while you are using Map instead of setting each item in Firestore Array. After reviewing it, Integromat expects objects with the following fields as arrays that you need to create and pass instead of using widgets[] as you have done in the current implementation.
[
value : 0,
valueType : "integerValue"
]
To achieve this, I have created the following Scenario(Not Sure how operation effective is it, but I get it working),
Data Structure Used is following which you can use through the generator and is used for Aggregator and Parse JSON module,
[{
"value": 0,
"valueType": "integerValue"
}, {
"value": 1,
"valueType": "integerValue"
}, {
"value": 2,
"valueType": "integerValue"
}]
Array Aggregator in second last step will then aggregate value and valueType and will be used in Google FireStore as,

Related

Change data type from string to date while skipping missing data

The core collection (other collections in the DB refer back to this one) in my DB contains 3 fields with date information which at this point is formatted as strings like MM/DD/YYYY. Further, there are a range of documents for which this field contains missing data, i.e. "". I populated this collection by running the mongoimport command on a JSON file.
My goal is to convert these date-fields into actual ISODate data types, so as to allow filtering the collection by dates. Further, I want MongoDB to know that empty strings indicate missing values. I have read quite widely on this, leading me to try a bunch of things:
Trying a forEach statement - This worked, but only for the very first document.
db.collection.find().forEach(function(element){
element.startDate = ISODate(element.startDate);
db.collection.save(element);
})
Using kind of a for-loop: this worked well, but stopped once it encountered a missing value (so it transformed about 11 values):
db.collection.update(
{
"startDate":{
"$type":"string"
}
},
[
{
"$set":{
"startDate":{
"$dateFromString":{
"dateString":"$startDate",
"format":"%m/%d/%Y"
}
}
}
}
]
)
So, both of these approaches kind of worked - but I don't know how to apply them to the entire collection. Further, I'd be interested in performing this task in the most efficient way possible. However, I only want to do this once - data that will be added in the future should hopefully be correctly formatted at the import stage.
db.collection.updateMany(
{
"$and": [
{ "startDate": { "$type": "string" } },
{ "startDate": { "$ne": "" } }
]
},
[
{
"$set": {
"startDate": {
"$dateFromString": {
"dateString": "$startDate",
"format": "%m/%d/%Y"
}
}
}
}
]
)
Filtering out empty string than doing the transformation will ignore documents that have empty string in date field.

MERN stack, Mongodb updating all embedded document arrays with this value if they have a certain value

I am trying to updateMany() documents which are an array of documents, if they have a certain value. I am still learning mongodb and I know how to update all documents if they have this value with my new value. The problem I think I am having is that they are an array of documents so I need to go into each document find the field called courses go inside of it and find the document called name and then update it the value of name and I have been trying, but no luck. Also In the request I update the first collection no problem its when I get into the next collection where it does nothing like I already mentioned.
request.body.code = request.sanitize(request.body.code);
request.body.name = request.sanitize(request.body.name);
request.body.courses.forEach(course => {
course.code = request.sanitize(course.code);
course.name = request.sanitize(course.name);
});
let newValues = { $set: {"code": request.body.code, "name":request.body.name } };
result = await mongoClient.db(DB_NAME).collection("all_courses").updateOne(selector, newValues);
// Okay now try to update other collection of array documents which isnt working yet
selector = { "code": "PROG2700"};
newValues = { $set: {"code": request.body.code, "name": request.body.name } };
console.log("this is new values");
console.log(request.body.courses);
result = await mongoClient.db(DB_NAME).collection("technologies").updateMany(selector,newValues);
That is in my server doing the mongodb work and trying to update the documents.
let sendString:Object = {
"id": my,
"code": edit_Course?.code,
"name": state_category_name,
"courses":
[
{
"code": edit_Course?.code,
"name": state_category_name
}
]
}
That is what I am sending to the server as the request.body
{
"_id": "5fdaa52060689aa159e4122e",
"name": "Webpack",
"description": "Webpack is great",
"difficulty": 2,
"courses": [
{
"code": "PROG2700",
"name": "Client Side Programming"
},
{
"code": "PROG3017",
"name": "Full Stack Programming"
}
]
}
That is what the mongodb structure of each document looks like in the technologies collection that I am having trouble updating. Its the name field I need to update in every document under courses. Could anyone give me a helping hand, many thanks!
Your selector filter doesn't work for the technologies class because the matching code field is part of an array named courses. To account for this, the filter should look something like this:
{ "courses.code": "PROG2700" }
This is an example of querying a field in a document embedded in an array.
The next step is to update the right document in the array. This can be done in MongoDB using the positional operator $. The update document would look like this:
{ $set: { "courses.$.code": request.body.code, "courses.$.name": request.body.name }}
In this update document, the positional operator tells MongoDB to update the code and name fields of the first document in the courses array with a code of PROG2700.
Put together, the update might look like this:
filter = { "courses.code": "PROG2700" };
update = { $set: { "courses.$.code": request.body.code, "courses.$.name": request.body.name }};
result = await mongoClient.db(DB_NAME).collection("technologies").updateMany(filter,update);

Mongodb: Update a field with data from a sub-sub field?

I'm trying to update a field in a collection with data from the same collection, but from a sub-sub field in it, and either can't get the syntax right, or I'm just doing it wrong.
I've spent quite some time now digging around here, but can't seem to get anywhere.
Here's the example structure of the users collection:
{
"_id": "12345qwerty",
"services": {
"oauth": {
"CharacterID": 12345678,
"CharacterName": "Official Username",
},
},
"name": "what I want to change",
"username": "OfficialUsername"
}
What I'm trying to do would be pretty trivial with SQL, ie: update all the display names to match a trusted source...
update users
set name = services.oauth.CharacterName;
...but I'm having trouble getting in MongoDB, and I have a feeling im doing it wrong.
Here's what i have so far, but it doesn't work as expected.
db.users.find().snapshot().forEach(
function (elem) {
db.users.update(
{ _id: elem._id },
{ $set: { name: elem.services.oauth.CharacterName } }
);
}
);
I can set the name to be anything at the base level, but can't set it to be something from the sublevel, as it doesn't recognise the sub-fields.
Any help would be greatly appreciated!
db.users.update({"services.oauth.CharacterName": {$exists: true}},{$set: {"name": "services.oauth.CharacterName"}},{multi:true})
I am setting name at the root of your document to be equal to the value in services.oauth.CharacterName in the sub sub document. multi = true will update multiple document, I am only updating documents that have the services.oauth.CharacterName value.

Morphia query to filter and fetch an embedded list element

I am new to NoSQL and morphia. I am using Morphia to query MongoDB.
I have a sample collection as below:
[
{
"serviceId": "id1",
"serviceName": "ding",
"serviceVersion": "1.0",
"files": [
{
"fileName": "b.html",
"fileContents": "contentsA"
},
{
"fileName": "b.html",
"fileContents": "contentsB"
}
]
},
{
"serviceId": "id2",
"serviceName": "ding",
"serviceVersion": "2.0",
"files": [
{
"fileName": "b.html",
"fileContents": "contentsA"
},
{
"fileName": "b.html",
"fileContents": "contentsB"
}
]
}
]
I would like to fetch an element in "files" List , given service name, service version and filename., using Morphia.
I was able to get what I want using the query below:
db.ApiDoc.find({ serviceName: "ding", serviceVersion: "2.0"}, { files: { $elemMatch: { fileName: "b.html" } } }).sort({ "_id": 1}).skip(0).limit(30);
What I tried so far :
I tried using "elemmatch" api that morphia has, but no luck.
query = ...createQuery(
Result.class);
query.and(query.criteria("serviceName").equal("ding"),
query.criteria("serviceVersion").equal(
"2.0"));
query.filter("files elem",BasicDBObjectBuilder.start("fileName", "a.html").get());
I seem to get the entire Result collection with all the files. I would like to get only the matched files(by filename).
can some one help me how I can get this to work?
Thanks
rajesh
I don't believe it's possible to get just the matching sub element. You can request just to have the 'files' array returned but all elements will be included in the result set and you will have to refilter in your code.
The other option is to make Files a collection of its own with a serviceId field and then you'll have more power to load only certain files.
It's possible to do that.
the filter doesn't really work like projection.
try this :
datastore.createQuery(Result.class)
.field("serviceName").equal("dong")
.field("serviceVersion").equal("2.0")
.field("files.filename").equal("a.html")
.project("files.$.filename", true);

sailsjs array query Exact match

i want to query mongodb in sailsjs.
this is structure of my db
{
"users": [
"52ed09e1d015533c124015d5",
"52ed4bc75ece1fb013fed7f5"
],
"user_msgs": [
{
"sender": "52ed09e1d015533c124015d5",
"sendTo": "52ed4bc75ece1fb013fed7f5",
"msg": "ss"
}
],
"createdAt": ISODate("2014-02-06T16:12:17.751Z"),
"updatedAt": ISODate("2014-02-06T16:12:17.751Z"),
"_id": ObjectID("52f3b461f46da23c111582f6")
}
I want to search those "users" who who match array [
"52ed09e1d015533c124015d5",
"52ed4bc75ece1fb013fed7f5"
]
Message.find({user: ["52ed09e1d015533c124015d5","52ed4bc75ece1fb013fed7f5"]})
this query returns all objects which contains 1 OR 2 ..but i need only those which exacly match 1 AND 2,
i have also tried $all, and etc.. but did not worked
please tell me how to write query with sailsjs supported syntex to get those user
You'll need to use the native Mongo adapter for this:
Message.native(function(err, collection) {
collection.find({users:{'$all':["52ed09e1d015533c124015d5","52ed4bc75ece1fb013fed7f5"]}}).toArray(function(err, results) {
// Do something with results
});
});
Message.find()
.where({users: "52ed09e1d015533c124015d5", "52ed4bc75ece1fb013fed7f5"})
.exec(function(){
// do something
});
While the above code may work to pull in just those users. I think a better solution would be to define your user ID's in your message model.
I would add the following attributes to your messages model:
senderID: {
type: 'string'
},
receiverID: {
type: 'string'
}
Now you can make that query more efficient by using the following query:
Message.find()
.where({senderID: "52ed09e1d015533c124015d5"})
.where({receiverID: "52ed4bc75ece1fb013fed7f5"})
.exec(function(){
// do something
});
This is the route I would take.