mongoengine connection and multiple databases - mongodb

I have 2 databases I want to query from, but I only get results from one. I'm using mongoengine with python and graphene (it's my first time). I've exhausted my search and I don't understand how I can resolve this issue. Here is my code:
import graphene
from mongoengine import Document, connect
from mongoengine.context_managers import switch_collection
from mongoengine.fields import (
StringField,
UUIDField,
IntField,
FloatField,
BooleanField,
)
from graphene_mongo import MongoengineObjectType
from mongoengine.connection import disconnect
class UserModel(Document):
meta = {"collection": "users"}
userID = UUIDField()
first_name = StringField()
last_name = StringField()
class Users(MongoengineObjectType):
class Meta:
model = UserModel
class UsersQuery(graphene.ObjectType):
users = graphene.List(Users)
user = graphene.Field(Users, userID=graphene.UUID())
def resolve_users(self, info):
db = connect("users")
users = list(UserModel.objects.all())
db.close()
return users
def resolve_user(self, info, userID):
return UserModel.objects(userID=userID).first()
users_schema = graphene.Schema(query=UsersQuery)
import graphene
from mongoengine import Document, connect
from mongoengine.fields import StringField, UUIDField
from graphene_mongo import MongoengineObjectType
from mongoengine.connection import disconnect
class Workout(Document):
meta = {"collection": "workouts"}
workoutID = UUIDField()
workout_label = StringField()
class Workouts(MongoengineObjectType):
class Meta:
model = Workout
class Query(graphene.ObjectType):
workouts = graphene.List(Workouts)
workout = graphene.Field(Workouts, workoutID=graphene.UUID())
def resolve_workouts(self, info):
db = connect("workouts")
wks = list(Workout.objects.all())
db.close()
return wks
def resolve_workout(self, info, workoutID):
return Workout.objects(workoutID=workoutID).first()
workouts_schema = graphene.Schema(query=Query)
Now when I have my python server up, mongod running I can hit the /workouts and it will return the array I need. But /users will not return the results.
I get no errors, nothing is wrong with my graphene query.
I can only get one of the queries to work at once.
I have tried using alias, not closing the connections, declaring the connect at the top level even before class UserModel or Workout.

If each of your model is bound to a different database. You should use something like this (cfr docs):
connect('workouts', alias='dbworkouts') # init a connection to database named "workouts" and register it under alias "dbworkouts"
connect('users', alias='dbusers')
class Workout(Document):
meta = {"db_alias": "dbworkouts"}
workoutID = UUIDField()
...
class UserModel(Document):
meta = {"db_alias": "dbusers"}
userID = UUIDField()
...

Related

Writing to multiple tables using sqlalchemy, fastapi, pydantic postgres

First API I've built so bear with me, I currently have a FastAPI that is supposed to save a record of an event and when it happened, as well as a list of people who assisted with each event. Currently, my crud.py "post" command currently only posts to 'test', but I also need it to post names of those who helped to 'whohelped'. I've tried to make 'whohelped.event_token' the foreign key of 'Save_Info.token'. A check on whether my models and schema are correctly made would be greatly appreciated. The main issue is I'm totally lost how to make "post" make changes to both tables at once.
models.py
from .database import Base
from sqlalchemy import Column, String, Integer, Date, ForeignKey
from sqlalchemy.orm import relationship
class Save_Info(Base):
__tablename__ = 'test'
token = Column(Integer, primary_key = True, autoincrement = True)
how = Column(String)
date = Column(Date)
children = relationship("Who_Helped",back_populates="test")
class Who_Helped(Base):
__tablename__ = 'whohelped'
id = Column(Integer, primary_key = True, autoincrement = True)
event_token = Column(Integer, ForeignKey('test.token'))
who_helped = Column(String)
schema.py
from pydantic import BaseModel
from typing import Optional, List
from sqlalchemy.orm import relationship
from sqlalchemy import DateTime
class Who_Helped(BaseModel):
id: int
event_token: int
who_helped: Optional[str]
class Save_Info(BaseModel):
token: int
how: str
date: str
class Config:
orm_mode = True
crud.py
from sqlalchemy.orm import Session
from . import schema, models
def post_info(db: Session, info: schema.Save_Info):
device_info_model = models.Save_Info(**info.dict())
db.add(device_info_model)
db.commit()
db.refresh(device_info_model)
return device_info_model
def get_info(db: Session, token: int = None):
if token is None:
return db.query(models.Save_Info).all()
else:
return db.query(models.Save_Info).filter(models.Save_Info.token == token).first()
def error_message(message):
return {
'error': message
}
main.py
from fastapi import FastAPI, Depends, HTTPException
from .database import SessionLocal, engine
from sqlalchemy.orm import Session
from .schema import Save_Info
from . import crud, models
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
def db():
try:
db = SessionLocal()
yield db
finally:
db.close()
#app.post('/device/info')
def post_info(info: Save_Info, db=Depends(db)):
object_in_db = crud.get_info(db, info.token)
if object_in_db:
raise HTTPException(400, detail= crud.error_message('This account of saving the world already exists'))
return crud.post_info(db,info)
#app.get('/device/info/{token}')
def get_info(token: int, db=Depends(db)):
info = crud.get_info(db,token)
if info:
return info
else:
raise HTTPException(404, crud.error_message('No info found for this account of saving the world {}'.format(token)))
#app.get('/device/info')
def get_all_info(db=Depends(db)):
return crud.get_info(db)

Implementation of count(*) in Graphene / Mongo

Good afternoon,
How may I implement a count of items back of MongoDB request and make it available through GraphQl request ? I am currently using MongoDB <=> MongoEngine <=> graphene <=> Flask .
Any help will be welcomed .
Thanks
B.
After a lot of time, reading forums and Internet pages, I am now able to retrieve the total count of entity send back from MongoDB.
Here is the Models.py
from mongoengine import Document
from mongoengine.fields import StringField
class User(Document):
meta = {'collection': 'user'}
first_name = StringField(required=True)
last_name = StringField(required=True)
Here is the Schema.py
from graphene_mongo import MongoengineObjectType,MongoengineConnectionField
import graphene
from graphene.relay import Node
from Models import User as UserModel
from mongoengine import connect
from flask import Flask
from flask_graphql import GraphQLView
connect(db="graphene-mongo-example",host="127.0.0.1:27017",alias="default")
class Connection(graphene.Connection):
class Meta:
abstract = True
total_count = graphene.Int()
def resolve_total_count(self, info):
return len(self.edges)
class User(MongoengineObjectType):
class Meta:
model = UserModel
interfaces=(Node,)
filter_fields = {'first_name': {'startswith', 'contains'}, 'last_name': [""]}
connection_class = Connection
class Query(graphene.ObjectType):
Node=Node.Field()
all_users = MongoengineConnectionField(User)
schema = graphene.Schema(query=Query)
app = Flask(__name__)
app.debug = True
app.add_url_rule(
"/graphql", view_func=GraphQLView.as_view("graphql", schema=schema, graphiql=True,types=[User])
)
if __name__ == "__main__":
app.run()
To run this example :
python Schema.py

Cannot access data after full text search using sqlalchemy, postgres and flask

I would like to search my postgres data base using postgres build-in full text search capability. In my app I have a set of posts stored according to title, content and date.
I think I can search the database using tsvector, but cannot retrieve the data from the results; i.e. the title, the content and the date. Could anyone help me, please?
import json, sys
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects import postgresql
from sqlalchemy.sql.expression import cast, func
from sqlalchemy import Index
def create_tsvector(*args):
exp = args[0]
for e in args[1:]:
exp += ' ' + e
return func.to_tsvector('english', exp)
app = Flask(__name__)
app.config['SECRET_KEY'] = 'some_key'
app.config["SQLALCHEMY_DATABASE_URI"] = 'postgresql:somedb'
db = SQLAlchemy(app)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Text, nullable=False)
content = db.Column(db.Text, nullable=False)
date = db.Column(db.Text,unique=False)
__ts_vector__ = create_tsvector(
cast(func.coalesce(content, ''), postgresql.TEXT)
)
__table_args__ = (Index('idx_post_fts', __ts_vector__, postgresql_using='gin'), )
def __repr__(self):
return f"Post('{self.title}', '{self.date}')"
if len(sys.argv) > 1:
filename1 = sys.argv[1]
infile=open(filename1,'r')
posts=json.load(infile)
infile.close()
List=list(posts)
art = 0
for j in range(0,len(List)):
if j % 10 == 0:
print(j)
title= posts[List[art]]['Title']
date = posts[List[art]]['Posted']
content=posts[List[art]]['Text']
post = Post(title=title, date=date, content=content)
db.session.add(post)
db.session.commit()
art+=1
from sqlalchemy.dialects.postgresql import TSVECTOR
from sqlalchemy import select, cast
posts = Post.__ts_vector__.match("bicycle", postgresql_regconfig='english')
print(posts)

insert_many not working when adding one more case

I used the following code to insert tab0011.json into portal_db.acs:
from pymongo import MongoClient
import json
client = MongoClient()
db = client.portal_db
db.acs.drop()
acs = db.acs
data_acs = json.load(open('/vagrant/data/tab0011.json', 'r'))
result_acs = acs.insert_many(data_acs)
The code has stored the tab0011.json data correclty. However, I tried the following code to insert tab0011.json into portal_db.acs and tab0007.json into portal_db.tab0007. Both collections were created but with none inside, i.e., empty:
from pymongo import MongoClient
import json
client = MongoClient()
db = client.portal_db
db.acs.drop()
acs = db.acs
db.tab0007.drop()
tab0007 = db.tab0007
data_acs = json.load(open('/vagrant/data/tab0011.json', 'r'))
data_tab0007 = json.load(open('/vagrant/data/tab0007.json', 'r'))
result_acs = acs.insert_many(data_acs)
result_tab0007 = tab0007.insert_many(data_tab0007)
Not quite sure why.
If the file extension is .json I am able to read the data via the methods used in your code and insert them into collections in the same database. I can see the data that I used in both the respective collections
Maybe you can try doing it this way:
from pymongo import MongoClient
import json
client = MongoClient(host="localhost", port=27017)
db = client["portal_db"]
acs = db.get_collection("acs")
tab0007 = db.get_collection("tab0007")
db.drop_collection("acs")
db.drop_collection("tab0007")
data_acs = json.load(open('/vagrant/data/tab0011.json', 'r'))
data_tab0007 = json.load(open('/vagrant/data/tab0007.json', 'r'))
acs_inserts = acs.insert_many(data_acs)
tab_inserts = tab0007.insert_many(data_tab0007)
print(acs_insert.inserted_ids)
print(tab_inserts.inserted_ids)
The last two lines would print the ObjectIds of the Documents inserted.

How to get e-mail address of current Jenkins user to use in groovy script

I've created a groovy script for the new Jenkins Workflow Plugin, https://github.com/jenkinsci/workflow-plugin. I want it to send a mail to the user who started the job when it needs input for the next step. I've tried to search the API but I can't find anything about getting the users email address.
I would think of something like this.
import hudson.model.User
def user = User.current()
def mailAddress = user.getMailAddress()
Is there a way to get the current Jenkins user' address in groovy?
I found a way:
import hudson.model.AbstractProject
import hudson.tasks.Mailer
import hudson.model.User
def item = hudson.model.Hudson.instance.getItem(env.JOB_NAME)
def build = item.getLastBuild()
def cause = build.getCause(hudson.model.Cause.UserIdCause.class)
def id = cause.getUserId()
User u = User.get(id)
def umail = u.getProperty(Mailer.UserProperty.class)
print umail.getAddress()
You can access the object of the current user with the method current()
def user = hudson.model.User.current();
The email address can be retrieved in the same way as to what you have done in your answer.
print user.getProperty(hudson.tasks.Mailer.UserProperty.class).getAddress();
import hudson.tasks.Mailer;
import hudson.model.User;
import hudson.model.Cause;
import hudson.model.Cause.UserIdCause;
def cause = build.getCause(hudson.model.Cause$UserIdCause)
def id = cause.getUserId()
User u = User.get(id)
def umail = u.getProperty(Mailer.UserProperty.class)
print umail.getAddress()
If you have access to the build variable in the Java code of your plugin (for instance in the setUp() method of the class that extends BuildWrapper), you can get the currently logged user this way :
#Override
public MyJenkinsPlugin setUp(AbstractBuild build, Launcher launcher, BuildListener listener)
String connectedUser = build.getCause(Cause.UserIdCause.class).getUserId();
String mail = User.get(connectedUser.getProperty(hudson.tasks.Mailer.UserProperty.class).getEmailAddress()
...
}
I have not been able to get the logged user using User.current().getId(), it always returned me 'SYSTEM'.
Hope it helps!
You can get the author name and then use it for an example on a mailing registry or something like that:
def author = ""
def changeSet = currentBuild.rawBuild.changeSets
for (int i = 0; i < changeSet.size(); i++)
{
def entries = changeSet[i].items;
for (int i = 0; i < changeSet.size(); i++)
{
def entries = changeSet[i].items;
def entry = entries[0]
author += "${entry.author}"
}
}
print author;
You can use the following routine:
import hudson.tasks.Mailer;
import hudson.model.User;
/**#
* Get user's email
*
* #param id null for a user who triggered the current build or name otherwise
* #return user's email
*/
def getUserEmail(String id=null) {
User user = User.getById(id ?: currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId(), false)
user?.getProperty(Mailer.UserProperty.class).getAddress()
}