how do i iterate a cursor in pymongo - mongodb

i am currently working on a project and i have created two collections in my mongodb .
i want to be able to get a particular field out of the collection
here is the code
app = mongo.db.apps
find_app = app.find({'email':session['email']})
x = []
for apps in find_app:
x.append(apps)
print(x)
this prints [{'_id': ObjectId('5bb07458e58fb90fc8a60d49'), 'email': 'celviuks#ge.com', 'app_name': 'apply', 'version': '1'},
{'_id': ObjectId('5bb0795ae58fb90c18bf7f5e'), 'email': 'celvius#egg.com', 'app_name': 'egg', 'version': '1'}]
and i want only the app_name field
please how to i achieve this?

i solved it with less code
app = mongo.db.apps
find_app = app.find({'email':session['email']}, {app_name: 1, _id: 0})
done_apps = [doc['appname'] for doc in find_app]
return render_template('somepage.html',done_apps=done_apps)

Try this:
app = mongo.db.apps
find_app = app.find({'email':session['email']},
{app_name: 1, _id: 0})
x = []
for apps in find_app:
x.append(apps)
print(x)

Related

mongoose replace the current values in an array with new one NOT adding new values to the existing values in the array

Currently I have this mongoose schema and model:
let mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/whatever', { useNewUrlParser: true, useUnifiedTopology : true });
var Schema = mongoose.Schema;
var categorySchema = new Schema({
name: String,
description: String,
sortorder: Number,
isactive : { type: Boolean, default: true } ,
schedule : [] ,
});
var Category = mongoose.model('Category', categorySchema);
module.exports = Category;
schedule array get days of the week and open/close hours for everyday of the week.
When I try to update the schedule array, it adds to the previous values but I want to wipe those values and write new values in the array. This is how I use the model in my express route:
app.post('/categoryschedule', (req, res) =>{
let data = req.body
let filter = {_id : data.id}
let updated = {schedule : data.schedule }
Category.findByIdAndUpdate(filter, updated, {new : true}, function (error, results){
if (error) {
console.log("-----error ------- :", error)
}
res.json({"schedule update ": "category schedule updated", "resultsfromscheduleupdate" : results})
})
})
Currently, if I enter a schedule like 1,2,3,4,5,6,7 into the array and then edit the schedule to be 8, 9, 10, 11, 12, 13, 14 I get 1 2 3 4 5 6 7 8 9 10 11 12 13 14 but I want the update to replace 1 2 3 4 5 6 7 with 8 through 14 so array after update would only include values of 8 through 14.
So every time I update the schedule, it adds the new values to whatever existed in the array before the update. I used $set and read the doc but unable to do it. It seems like once I write to the array, I can't erase the values already exited and write new ones.
Maybe I misunderstood the doc. To be clear, my question is how to replace the values already exist in the array schedule with new one - wipe the array empty every time I update the schedule - and add the new values to the array.
schedule : Array
0: {weekdayname: 'Monday', weekdaynumber: 1, openhours: '10'...}
1: {weekdayname: 'Tuesday', weekdaynumber: 2, openhours: '10', …}
2: {weekdayname: 'Wednesday', weekdaynumber: 3, openhours: '10', …}
3: {weekdayname: 'Thursday', weekdaynumber: 4, openhours: '10', …}
4: {weekdayname: 'Friday', weekdaynumber: 5, openhours: '10', …}
5: {weekdayname: 'Saturday', weekdaynumber: 6, openhours: '10' …}
6: {weekdayname: 'Sunday', weekdaynumber: 0, openhours: '10' …}
Anyone with experience in mongoose arrays or what type of datatype for store arrays and array of objects in mongoose?
If it is not possible, then how do I get to specific array element, let us say, I want to get to schedule[0].openhours
How to I update using model.findOneAndUpdate ({filter by id}, {scheudle[0].openhours : "updated value"}) it is not updating the targeted doc.
How to reference array elements in mongoose update fn?

applyTransaction remove not working with id

I'm using ag-grid in Angular9 project. I'm using Transactions to do CRUD operations in grid when my backend request resolve. I need to provide RowNodeId myself, i dont want to use object-references as i have large data set.
Thing is, i've provided the ID and i can add/update item in the grid but i'm unable to delete the item. In Doc it mentions, you only need to provide id to remove the item but i'm getting the following error.
Here's the code.
class HostAppListPage
{
#ViewChild('agGrid', {static: true}) grid:AgGridAngular;
constructor()
{
}
ngOnInit()
{
this.grid.getRowNodeId = (data) => {
return data.entityId;
};
this.columns = [
{headerName: 'App Name', field: 'name', rowDrag: true, headerCheckboxSelection: true, checkboxSelection: true},
{headerName: 'App Id', field: 'id'},
{headerName: 'Compatibility', field: COMPATIBILITY'},
{headerName: 'Creation', field: 'createdAtToString'},
{headerName: 'Last Update', field: 'updatedAtToString'}
];
}
deleteRow()
{
let ids = this.gridApi.getSelectedNodes()
// .map((row) => {
// return {id: row.entityId}
// return row.entityId;
// });
console.log(ids);
this.grid.api.applyTransaction({remove: ids});
}
I tried both with and without map statement, nothing worked
but my Add and Update works fine.
Replace map with following code.
.map((row) => {
return {entityId: row.data.entityId};
});
it should be the the same field (entityId) which i set in getRowNodeId function.
In a typical situation, where one does not define a getRowNodeId, one should be able to do:
const removeData: any[] = [{id: rowNode0.id}, {id: rowNode1.id}, ...];
applyTransaction({remove: removeData});
where rowNode0, rowNode1, etc. are the nodes you want to remove.
However when you provide your own getRowNodeId callback, ag-grid will fetch the id's by applying your callback on the data you provided. Therefore, the name(s) in the data must match those used in your callback. That's why return {id: row.entityId} doesn't work, but return {entityId: row.entityId} does.
In other words, if one defines:
this.grid.getRowNodeId = (data) => {
return data.column1 + data.column5 + data.column2;
};
Then one would need to provide
const removeData: any[] = [
{column1: 'a1', column2: 'b1', column5: 'c1'},
{column1: 'a2', column2: 'b2', column5: 'c2'},
{column1: 'a3', column2: 'b3', column5: 'c3'},
];
so that ag-grid would have all the names it needs to find the id's via the given getRowNodeId.

mailchimp3 (Python-mailchimp-api) How to set tags

I tried:
client.lists.members.create('1111111', {
'email_address' : 'frogger116#gmail.com',
'status' : 'subscribed',
"tags": [{'name': 'frogger', 'status' : 'active'}],
})
and get:
mailchimp3.mailchimpclient.MailChimpError: {
'type': 'http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/',
'title': 'Invalid Resource',
'status': 400,
'detail': 'Expected argument of type "string", "stdClass" given',
'instance': '5ae1b966-ed35-49f1-ad32-0a39c3d63593'
}
Without the "tags" line the satement works
This works for me (you need hash the email address)
hash = get_subscriber_hash(email_address)
data = {
'tags': [
{'name': 'foo', 'status': 'active'},
{'name': 'bar', 'status': 'inactive'}
]
}
client.lists.members.tags.update(list_id=list_id, subscriber_hash=hash, data=data)
I think in the latest version the tags are just strings. At least, this is what I use.
client.lists.members.create('1111111', {
'email_address' : 'frogger116#gmail.com',
'status' : 'subscribed',
'tags': ['frogger','invaders']
})
Also, to be certain, make sure tags exist in the system. Especially if doing an update rather than insert. Its not super consistant about dealing with unknown tags.
Also of course, make sure the '1111111' audience id exists.
SUPPLEMENTAL CODE
Of course, I've found a better way to ensure what you want is to use other methods to add to tags rather than on insert. You may have to tweak the below functions as they are part of a class, but they should give you other ideas on how to add and remove tags from users
def bulkUpdateTagNamesForEmails(self, emailsToUpdate, tagNames, remove=False):
audienceId = self.audienceId
if remove:
data = {'members_to_remove':emailsToUpdate}
else:
data = {'members_to_add':emailsToUpdate}
segments = None
for tagName in tagNames:
segId,segments = self.getSegmentIdFromTagName(tagName,segments)
if segId:
self.brResponse = self.mcClient.lists.segments.update_members(list_id=audienceId, segment_id=segId, data=data)
def createTagNameIfNeeded(self, tagName):
audienceId = self.audienceId
# Check for tag name
found = False
segments = self.mcClient.lists.segments.all(list_id=audienceId, get_all=False)
for segment in segments['segments']:
if segment['name'] == tagName:
found = True
print("Found tag")
# If not found, create it
if not found:
print(f"Creating new tag {tagName}")
data = {'name': tagName,'static_segment': []}
self.mcClient.lists.segments.create(list_id=audienceId, data=data)
def getSegmentIdFromTagName(self,reqTagName,segments=None):
audienceId = self.audienceId
reqId = None
if not segments:
segments = self.mcClient.lists.segments.all(list_id=audienceId, get_all=True)
for segment in segments['segments']:
segName = segment['name']
segId = segment['id']
if segName == reqTagName:
reqId = segId
break
return reqId,segments

How to make Mongoose model.insertMany insert documents with numerical and ordered ids?

I have this route in the backend express server:
router.route('/fillInformationAssetsSeverityEvaluation').post((req, res) => {
informationAssetsSeverityEvaluationRow.remove({}, (err) => {
if (err)
console.log(err);
else
// res.json("informationAssets Collection has been dropped!");
res.json('information Assets Severity Evaluation data has been received on the server side')
informationAssetsSeverityEvaluationRow.insertMany([req.body[0]], {
multi: true
}).then(documentsInserted => {
console.log('[req.body[0]]: ', [req.body[0]]);
console.log('documentsInserted: ', documentsInserted);
console.log('You have succesfully inserted ', documentsInserted.length, ' documents in informationAssetsSeverityEvaluation collection');
});
});
})
For the sake of simplicity, I am inserting only one document.
[req.body[0]]
{ REF: 'REFSHIT',
confFin: 'A',
confRep: 'A'}
But, in the real applications, I am inserting multiple documents similar to that.
This consoleLog :
console.log('documentsInserted: ', documentsInserted);
logs:
documentsInserted: [ { _id: 5d3453afc302d718e4870b53,
REF: 'REFSHIT',
confFin: 'A',
confRep: 'A'}]
As you see the id is automatically generated:
> _id: 5d3453afc302d718e4870b53
What I would like is: The ids of the different documents to be "numerically ordered". I.e:
Document 0 would have id 0
Document 1 would have id 1
Document 2 would have id 2
And so on and so forth.
After having made some research, I found out that I can do this manually by inserting the id manually inside the updateMany objects.
However, since I receive the documents objects from the request body, this is not a viable solution.
Any help?
Finally after trying four modules and a couple of days of trying for something that should be native to mongodb, I have found a simple solution. I hope it helps someone.
1/ Install mongoose-plugin-autoinc
2/
import mongoose from 'mongoose';
import { autoIncrement } from 'mongoose-plugin-autoinc';
const connection = mongoose.createConnection("mongodb://localhost/myDatabase");
const BookSchema = new mongoose.Schema({
author: { type: Schema.Types.ObjectId, ref: 'Author' },
title: String,
genre: String,
publishDate: Date
});
BookSchema.plugin(autoIncrement, 'Book');
const Book = connection.model('Book', BookSchema);
2/ In my case I have the models defined in models.js and the connection defined in server.js so I had to write this :
BookSchema.plugin(autoIncrement, 'Book');
in models.js
and instead of
const Book = connection.model('Book', BookSchema);
I have:
module.exports = {
informationAssetsRow: mongoose.model('informationAssetsRow', informationAssetsRow),
};
And in server.js:
const {
informationAssetsRow,
} = require('./models/models')

MongoDB - "The dollar ($) prefixed field \'$$hashKey\' in \'fieldName".$$hashKey\' is not valid for storage.'"

While trying to update a document I'm getting the above error for the field timesToDisplay.
MongoDB version 2.6.7.
The whole model:
msg = {
'name': '',
'template': '',
'displayDurInMilliSec': 0,
'timesToDisplay': [],
'images': [],
'texts': [],
'screen': []
}
I guess I will be getting the same error with the other 3 array fields.
I've tried using $set but sill getting the same error.
The code:
function updateMessage(msg) {
var conditions = {_id: msg._id}
, update = { 'name': msg.name,
'template': msg.template,
'displayDurInMilliSec': msg.displayDurInMilliSec,
'timesToDisplay': msg.timesToDisplay,
'images': msg.images,
'texts': msg.texts,
'screen': msg.screen
}
messageModel.update(conditions, update, callback);
function callback(err, numAffected) {
if (!err) console.log(numAffected)
else console.log(err)
}
}
EDIT: The msg parameter is a document in itself:
{ _id: '557d58abd54955480db6694f',
name: 'msg99',
timesToDisplay: [ { startDate: '2015-06-19T21:00:00.000Z',
'$$hashKey': 'object:214',
endDate: '2015-06-25T21:00:00.000Z',
daysOfTheWeek: [Object],
startTimeOfDay: '11',
endTimeOfDay: '13' } ],
images: [],
texts: [],
screen: [ 1 ],
'$$hashKey': 'object:54',
displayDurInMilliSec: '40189',
template: 'templates/Template2.html' }
The $$hashkey field is added by AngularJS when working with ngRepeat or ngOptions. In the case of ngRepeat you can change the repeat string by appending track by $index to it. For using ngOptions you'll have to filter out that field yourself. AngularJS provides a quick solution for filtering it out: angular.toJson. This will filter out all fields prefixed with two dollar signs. Check out the documentation.
I realize that this isn't a MongoDB answer, but this specific error ($$hashkey), is usually due to AngularJS.