How to set a collection name in MongoDB - python

I encountered such a problem, I do not know how to set the name of this collection through the code when creating a collection, that is, I write:
cluster = MongoClient("link")
db = cluster.BananiData
collection = db.ctx.guild.id
but the name is set as ctx.guild.id, I need to insert the server ID in the name, how can this be implemented?
P.S: I use python
code:
cluster = MongoClient("mongodb+srv://Bananchik:hdkkIFkk6VKywSDH#cluster0.olcto.mongodb.net/<BananiData>?retryWrites=true&w=majority")
db = cluster.BananiData
collection = db.ctx.guild.id
#collection = cluster.BananiData.LevelSystem
class DataBases(commands.Cog):
""" ФСБ? """
def __init__(self, bot):
self.bot = bot
#commands.command()
#commands.check(permissions.is_owner)
async def test_db(self, ctx):
await ctx.send(collection)
await ctx.send("DB id created")
for member in ctx.guild.members:
print(member)
post = {
"_id": member.id,
"xp": 0,
"lvl": 1,
"message_count": 0
}
if collection.count_documents({"_id": member.id}) == 0:
collection.insert_one(post)
print(f"Пользователь **{member.name}** добавлен в базу данных")

It is a good practice to enclose the name you want to assign to a collection inside a
square bracket if you are using python.
Example:
If you want to create a collection by the name "SampleCollection", you could use the below command, even though
. operator works.
collection = db["SampleCollection"]
Therefore,
You should change the collection initialization code like the following:
collection = db[ctx.guild.id]
Note: Make sure that ctx.guild.id variable is of type str else it won't work.

Related

Foreignkey in route

i just started learning FastAPI, and i just created some model with ForeingKey(using tortoise), and in my route i have:
class DailyMontage(models.Model):
id = fields.IntField(pk=True, indexed=True)
team = fields.ForeignKeyField("models.Team", related_name="daily_montage", on_delete=fields.CASCADE)
type = fields.CharEnumField(utils.TypeDailyMontageUtils)
day_montage = fields.CharEnumField(utils.DayMontageUtils)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
DailyMontage_Pydantic = pydantic_model_creator(DailyMontage, name="DailyMontage", exclude=('created_at', 'updated_at',))
DailyMontageIn_Pydantic = pydantic_model_creator(DailyMontage, name="DailyMontageIn", exclude_readonly=True)
#daily_route.post('/daily/create')
async def create_daily(daily: DailyMontageIn_Pydantic):
daily_obj = await DailyMontage.create(**daily.dict(exclude_unset=True))
return await DailyMontage_Pydantic.from_tortoise_orm(daily_obj)
but in my localhost/docs when i want add object, i only see 2 fields like type and day_montage, i dont see team, whenever i add it manualy like team_id i have error like not permitt to add it
i was searching everywhere where i know, but everythink what is in google i only see basics models ..
SOLVED:
okay i solved my problem now is display list of items from Enum and added team_id to put:
#monter_route.post('/daily/create', tags=['Daily'])
async def create_daily(type_daily: TypeDailyMontageUtils, day_montage: DayMontageUtils,
team_id: int, ):
team = await Team.get(id=team_id)
daily_obj = await DailyMontage.create(type=type_daily, day_montage=day_montage, team=team)
return await DailyMontage_Pydantic.from_tortoise_orm(daily_obj)

Grab a User ID from a dict (Discord.py)

I've been getting the hang of Discord.py lately. Managing dictionaries, bot arguments, all that jazz. To finish off point management in my bot, I want to make a leaderboard. Following this answer, i structured my code slightly differently from them.
#bot.command(pass_context=True)
async def testboard(ctx, top:int=10):
total=[]
total = sorted(total,reverse=True)
board=discord.Embed(title = f'Top {top} highest awarded monkes.')
index = 1
if index == top:
return
else:
index += 1
for str in points:
userid = points[str]
user= bot.get_user(userid)
if index==1:
badge="\U0001F947"
elif index==2:
badge="\U0001F948"
elif index==3:
badge="\U0001F949"
else:
badge="\U0001F539"
board.add_field(name=f"**{badge}{index}. {user}**",value=(f"{points[str]} points"), inline=False)
await ctx.send(embed=board)
While it does display the points stored in my database, it doesn't do it from greatest to least, and doesn't display the name of the user.
As seen here: Result
I suspect it's because how my dictionary is structured.
{"userid": 0, "userid": 8, "userid": 0, "userid": 35, "userid": 11, "userid": 6}
Perhaps I can grab the name of the variable? If so, how can I do that?
The reason the username is just showing up as "None" is this portion of the code:
userid = points[str]
user= bot.get_user(userid)
If the str variable from the for loop is the user id, then the userid variable you are creating here is the point score for that user, not the id itself, so bot.get_user returns None because it won't find a user with, for example, an ID of 0. Change those lines to the following:
user= bot.get_user(int(str))
Secondly, the points are not in order because dictionaries are not ordered at all, so you would have to sort the objects manually. One way to do that is to get the entries of the dictionary, including both the key (the userid) and the value (number of points), sort it by points, and then iterate through it in a for loop:
for (userid, score) in sorted(points.items(), key=lambda entry: entry[1], reverse=True):
user= bot.get_user(int(userid))
if index==1:
badge="\U0001F947"
elif index==2:
badge="\U0001F948"
elif index==3:
badge="\U0001F949"
else:
badge="\U0001F539"
board.add_field(name=f"**{badge}{index}. {user}**",value=(f"{score} points"), inline=False)
I changed a couple of variable names here, most importantly str which is the class name for the string type, so it could potentially cause conflicts. Also, per your comment, the get_user method seems to require an integer and won't do conversion automatically.

Getting the keys, and not the values

So I want to get the json keys and compare them with the variable q
Json file
{
"api_key": "YOUR AUTOBUY API KEY",
"prefix": "PREFIX FOR BOT COMMANDS (for e.x !redeem, ?claim, etc",
"redeem_message": "Thanks for redeeming your order for {0}, I have added the ROLE_NAME_HERE role.",
"role_id": "REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING",
"redeem_channel_id": "REPLACE THIS WITH THE CHANNEL ID WHERE PEOPLE CAN USE THE REDEEM COMMAND",
"bot_token": "PUT YOUR DISCORD BOT TOKEN HERE"
}
Code
import json
def search(q):
with open("config.json") as f:
data = json.load(f)
for obj in data:
print(data[obj])
search(q="role_id")
Expected output: REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING (cause q = role_id and I want it to return the value of the key)
Actual output:
YOUR AUTOBUY API KEY
PREFIX FOR BOT COMMANDS (for e.x !redeem, ?claim, etc
Thanks for redeeming your order for {0}, I have added the ROLE_NAME_HERE role.
REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING
REPLACE THIS WITH THE CHANNEL ID WHERE PEOPLE CAN USE THE REDEEM COMMAND
PUT YOUR DISCORD BOT TOKEN HERE
Super simple, no need for a for loop if you just need one value:
import json
def search(q):
with open("config.json") as f:
data = json.load(f)
print(data[q])
search(q="role_id")
below
data = {'A':12,'B':13}
q = 'A2'
value = data.get(q)
if value is not None:
print(value)
else:
print('{} not found'.format(q))

accessing Kafka metadata with Python KafkaConsumer

I have a simple Kafka reader class. I really don't remember where I got this code. Could have found it, or my previous self may have created it from various examples. Either way, it allows me to quickly read a kafka topic.
class KafkaStreamReader():
def __init__(self, schema_name, topic, server_list):
self.schema = get_schema(schema_name)
self.topic = topic
self.server_list = server_list
self.consumer = KafkaConsumer(topic, bootstrap_servers=server_list,
auto_offset_reset = 'latest',
security_protocol="PLAINTEXT")
def decode(self, msg, schema):
parsed_schema = avro.schema.parse(schema)
bytes_reader = io.BytesIO(msg)
decoder = avro.io.BinaryDecoder(bytes_reader)
reader = avro.io.DatumReader(parsed_schema)
record = reader.read(decoder)
return record
def fetch_msg(self):
event = next(self.consumer).value
record = self.decode(event, self.schema)
return record
To use it, I instantiate an object and loop forever reading data such as this:
consumer = KafkaStreamReader(schema, topic, server_list)
while True:
message = consumer.fetch_msg()
print message
I'm sure there are better solutions, but this works for me.
What I want to get out of this, is the meta data on the Kafka record. A coworker in another group used Java or Node and was able to see the following information on the record.
{
topic: 'clickstream-v2.origin.test',
value:
{
schema:payload_data/jsonschema/1-0-3',
data: [ [Object] ] },
offset: 16,
partition: 0,
highWaterOffset: 17,
key: null,
timestamp: 2018-07-25T17:01:36.959Z
}
}
I want to access the timestamp field using the Python KafkaConsumer.
I have a solution. If I change the fetch_msg method I can figure out how to access it.
def fetch_msg(self):
event = next(self.consumer)
timestamp = event.timestamp
record = self.decode(event.value, self.schema)
return record, timestamp
Not the most elegant solution as I personally don't like methods that return multiple values. However, it illustrates how to access the event data that I was after. I can work on more elegant solutions

Flask Pymongo Objectid link not working

I am tring to access a new document from a mongo database collection named games by the _id. But for example if I access localhost:5000/solutie/5ae71f3e8e442b090e4c313bit is giving me the error: ValueError: View function did not return a response so it doesn't go through the if and I think I should convert the value of the _id to another type but I don't know how.
This is my flask code:
#app.route('/solutie/<id>')
def solu(id):
games = mongo.db.games
game_user = games.find_one({'_id' : id})
if game_user:
return id
This is my mongo database collection named games:
{
"_id": {
"$oid": "5ae71f3e8e442b090e4c313b"
},
"sursa1": "nothingfornow",
"sursa2": "nothing4now",
"corectat": 0,
"player2": "test",
"player1": "test2",
"trimis1": 1,
"trimis2": 1
}
There's an object type converter you can use for URL routing:
#app.route('/solutie/<ObjectID:game_id>')
def solu(game_id):
games = mongo.db.games
game_user = games.find_one_or_404({'_id' : game_id})
return game_user
See:
https://flask-pymongo.readthedocs.io/en/latest/#flask_pymongo.BSONObjectIdConverter
Also, don't override id() because this is an in-built Python function.
The second parameter of the find() method is an object describing which fields to include in the result.
This parameter is optional and if omitted, all fields are included in the result.
# #app.route('/solutie/<int:id>') # or
#app.route('/solutie/<string:id>')
def solu(id):
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["mydatabase"]
games = mydb["games"]
game_user = games.find({},{ "_id": id})
if game_user is not None:
return id
else:
return render_template("index.html")
Also you should use "else" condition.

Categories

Resources