MongoDB decimal rounder - mongodb

I used morphia for MongoDB aggregation to data. but I need to round my aggregation pipeline projection data. my code is
aggregationPipeline.project(
Projection.projection("_id").suppress(),
Projection.projection("query", "_id.query"),
Projection.projection("clicks", "clicks"),
Projection.projection("impressions", "impressions"),
Projection.projection("ctr", "ctr"),
Projection.projection("position", "position")
);
My Output is
{
"query": "google",
"clicks": 5,
"impressions": 16,
"ctr": 0.19375,
"position": 3.39375,
},
but i expect that
{
"query": "google",
"clicks": 5,
"impressions": 16,
"ctr": 0.19,
"position": 3.39,
},

Related

MongoDb Aggregation separated array based on condition

I'm very new to mongodb. I'm trying to do an aggregation pipeline for lookup kinda like SQL left join. Given the following document's schema:
Mongo playground: https://mongoplayground.net/p/yAIwH5V2yv8
Characters:
{
"_id": 1,
"account_id": 1,
"world_id": 0,
"name": "hello"
}
Inventories:
{
"_id": 7,
"character_id": 2,
"type": "EQUIPPED"
}
Items:
{
"_id": 1,
"inventory_id": 7
}
I want to query for characters and look up inventories as well as items in inventories. I was able to achieve this however I would like to separate the inventories field in characters result document.
Current result:
{
"_id": 2,
"account_id": 1,
"world_id": 0,
"name": "hello",
"inventories: [
{
"_id": 1,
"character_id": "2",
"type": "EQUIPPED",
"items: [...]
}
]
}
What I want is based on the type of inventory I want it to be a separate field of the resulted character document something like this:
{
"_id": 2,
"account_id": 1,
"world_id": 0,
"name": "hello",
"equippedInventory: {
"_id": 1,
"character_id": "2",
"type": "EQUIPPED",
"items: [...]
},
"equipInventory: {
"_id": 2,
"character_id": "2",
"type": "EQUIP",
"items: [...]
},
}
Also, is my pipeline the best way to achieve this?

Remove empty space from Streamlit Echarts

I am rendering a gauge component in the following way, within my Streamlit app:
option = {
"series": [
{
"type": "gauge",
"startAngle": 180,
"endAngle": 0,
"min": min_range_val,
"max": max_range_val,
"center": ["40%", "40%"],
"splitNumber": 5,
"axisLine": {
"lineStyle": {
"width": 6,
"color": [
[0.25, "#FF403F"],
[0.5, "#ffa500"],
[0.75, "#FDDD60"],
[1, "#64C88A"],
],
}
},
"pointer": {
"icon": "path://M12.8,0.7l12,40.1H0.7L12.8,0.7z",
"length": "12%",
"width": 30,
"offsetCenter": [0, "-60%"],
"itemStyle": {"color": "auto"},
},
"axisTick": {"length": 10, "lineStyle": {"color": "auto", "width": 2}},
"splitLine": {"length": 15, "lineStyle": {"color": "auto", "width": 5}},
"axisLabel": {
"color": "#464646",
"fontSize": 12,
"distance": -60,
},
"title": {"offsetCenter": [0, "-20%"], "fontSize": 20},
"detail": {
"fontSize": 30,
"offsetCenter": [0, "0%"],
"valueAnimation": True,
"color": "auto",
"formatter": "{value}%",
},
"data": [{"value": value, "name": caption}],
}
]
}
st_echarts(option, width="450px", height="350px", key="gauge")
However, it seems like an additional empty extra white space is added at the bottom of the component (as from the following image).
How can I effectively remove that and keep only a tiny margin all around the gauge?
The following parameters must be added:
radius: '120%',
center: ['50%', '80%']
The latter one should be adjusted according to specific use cases.

Is it possible to query on a date object with the Matlab connector for MongoDB?

I have just started using MongoDB with Matlab (R2021b). Currently, I am using the mongoc class (https://ch.mathworks.com/help/database/ug/mongoc.html) to connect to my MongoDB database.
I am having issues querying on the date. I have the following collection:
{
"_id": 1,
"stock": "Stock1",
"value": 10,
"date": "2010-01-01T00:00:00.000Z"
},
{
"_id": 2,
"stock": "Stock1",
"value": 20,
"date": "2015-01-01T00:00:00.000Z"
},
{
"_id": 3,
"stock": "Stock1",
"value": 30,
"date": "2020-01-01T00:00:00.000Z"
}
And the end result would need to look as follows:
{
"_id": 2,
"stock": "Stock1",
"value": 20,
"date": "2015-01-01T00:00:00.000Z"
},
{
"_id": 3,
"stock": "Stock1",
"value": 30,
"date": "2020-01-01T00:00:00.000Z"
}
To do this, I have tried in Matlab:
conn = mongoc('localhost', 27017, database_name);
query = '{"date": {"$gte": ISODate("2015-01-01"), "$lte": ISODate("2020-01-01")}}';
res = find(conn, collection_name, 'Query', query);
However, I am getting the following error:
[Mongo Driver Error]: Got parse error at "S", position 19:
"SPECIAL_EXPECTED".
I have tried various ways of placing the quotation marks but none have proven successful. Querying with a similar string in MongoDB Compass however works. Has anyone overcome this issue or is the connector just not able to query on dates? Another solution would be to store the date in another format (int or float) and query on that, but I would like to avoid this kind of solution.
Any help would be greatly appreciated!

Why doesn't this pymongo subdocument find work?

I'm looking at using mongodb and so far most things that I've tried work. But I don't know why this find doesn't work.
col = db.create_collection("test")
x = col.insert_many([
{"item": "journal", "qty": 25, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A"},
{"item": "notebook", "qty": 50, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "A"},
{"item": "paper", "qty": 100, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "D"},
{"item": "planner", "qty": 75, "size": {"h": 22.85, "w": 30, "uom": "cm"}, "status": "D"},
{"item": "postcard", "qty": 45, "size": {"h": 10, "w": 15.25, "uom": "cm"}, "status": "A"}
])
cursor = col.find({"size": {"h": 14, "w": 21, "uom": "cm"}})
if cursor.retrieved == 0:
print("found nothing") # <<<<<<<<< prints this
As explained into docs into section Match an Embedded/Nested Document:
Equality matches on the whole embedded document require an exact match of the specified document, including the field order.
So, you have to set the object into find stage in the same order that exists into DB.
I really don't know if keys into objects follows an strict order (alphabetically or whatever) but using this query almost everything output the result. Not always so I think there is a "random" (or not possible to handle) concept to store data -at least into mongo playground-.
By the way, the correct way to ensure results is to use dot notation so this query will always works ok.
coll.find({
"size.h": 14,
"size.w": 21,
"size.uom": "cm"
})
I was thinking that cursor.retrieved was non zero if it found something. I guess not. I found that this works:
lst = list(cursor)
print(lst)
cursor.rewind()
print(list(cursor))
if len(lst) != 0:
for d in lst:
print(d)

Finding the highest value from a field

I have the following object in a mongodb. I'm wanting to find the genre that has won the highest number of awards, and out of the whole collection find the top 3 most found genres. I'm not really sure how to go about targeting specific fields within a collection like this, is it better to treat it as a large array? or is that a ridiculous comment.
Tried query which fails because the genre field is not an accumulator
db.MovieData.aggregate([
{$sort:{"awards.wins":-1}},
{$group:{"genres":"$genres"}}
])
Example data, there is far more data but i have limited it to 2 insertions
[
{
"title": "Once Upon a Time in the West",
"year": 1968,
"rated": "PG-13",
"runtime": 175,
"countries": [
"Italy",
"USA",
"Spain"
],
"genres": [
"Western"
],
"director": "Sergio Leone",
"writers": [
"Sergio Donati",
"Sergio Leone",
"Dario Argento",
"Bernardo Bertolucci",
"Sergio Leone"
],
"actors": [
"Claudia Cardinale",
"Henry Fonda",
"Jason Robards",
"Charles Bronson"
],
"plot": "Epic story of a mysterious stranger with a harmonica who joins forces with a notorious desperado to protect a beautiful widow from a ruthless assassin working for the railroad.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTEyODQzNDkzNjVeQTJeQWpwZ15BbWU4MDgyODk1NDEx._V1_SX300.jpg",
"imdb": {
"id": "tt0064116",
"rating": 8.6,
"votes": 201283
},
"tomato": {
"meter": 98,
"image": "certified",
"rating": 9,
"reviews": 54,
"fresh": 53,
"consensus": "A landmark Sergio Leone spaghetti western masterpiece featuring a classic Morricone score.",
"userMeter": 95,
"userRating": 4.3,
"userReviews": 64006
},
"metacritic": 80,
"awards": {
"wins": 4,
"nominations": 5,
"text": "4 wins \u0026 5 nominations."
},
"type": "movie"
},
{
"title": "A Million Ways to Die in the West",
"year": 2014,
"rated": "R",
"runtime": 116,
"countries": [
"USA"
],
"genres": [
"Comedy",
"Western"
],
"director": "Seth MacFarlane",
"writers": [
"Seth MacFarlane",
"Alec Sulkin",
"Wellesley Wild"
],
"actors": [
"Seth MacFarlane",
"Charlize Theron",
"Amanda Seyfried",
"Liam Neeson"
],
"plot": "As a cowardly farmer begins to fall for the mysterious new woman in town, he must put his new-found courage to the test when her husband, a notorious gun-slinger, announces his arrival.",
"poster": "http://ia.media-imdb.com/images/M/MV5BMTQ0NDcyNjg0MV5BMl5BanBnXkFtZTgwMzk4NTA4MTE#._V1_SX300.jpg",
"imdb": {
"id": "tt2557490",
"rating": 6.1,
"votes": 126592
},
"tomato": {
"meter": 33,
"image": "rotten",
"rating": 4.9,
"reviews": 188,
"fresh": 62,
"consensus": "While it offers a few laughs and boasts a talented cast, Seth MacFarlane's overlong, aimless A Million Ways to Die in the West is a disappointingly scattershot affair.",
"userMeter": 40,
"userRating": 3,
"userReviews": 62945
},
"metacritic": 44,
"awards": {
"wins": 0,
"nominations": 6,
"text": "6 nominations."
},
"type": "movie"
}
What you are looking for is:
db.MovieData.aggregate([
{ "$unwind": "$genres" },
{ "$group": {
"_id": "$genres",
"totalWins": { "$sum": "$awards.wins" }
}},
{ "$sort": { "totalWins": -1 } },
{ "$limit": 3 }
])
In short:
$unwind - The genres field is an array, you need that "flattened" in order to use as a "grouping key" for the next stage:
$group - Requires an _id which is the "grouping key" or the value that things are accumulated for. Though not a requirement this is typically paired with accumulators, which perform the "aggregation operations" such as $sum on a supplied field value. Here you want:
{ "$sum": "$awards.wins" }
to accumulate that field.
$sort - Orders those results by the supplied field(s). In this case on the accumulated totalWins and in descending ( -1 ) order.
$limit - Is the number of result documents to limit the return to.
A good place to look for common examples is the SQL to Aggregation Mapping Chart in the core documentation, particularly if you have some working knowledge of SQL or even if you do not as general examples.
All of the Aggregation Pipeline Stages as well as the Aggregation Pipeline Operators also have various usage examples within their own documentation pages as well. Familiarizing yourself with these is useful in understanding how they apply to different problems