Embedded vs. Referenced Documents mongoDB - mongodb

I'm starting to study mongodb, but I want to understand better when to use embedded or referenced documents.
the project I'm trying to make is something similar to a POS (point of sale), working like:
Every time that someone make a purchase, it inserts on the database, but, there are costumers with N groups of stores and theses "groups of stores" have N stores and N POS.
After this i want a database to update the prices in specific stores (not in groups) and make a summary of how many sales any POS made.
So, talking about perfomance what is the best design and why?
here are some exemples that I made:
Embedded :
{
"group1": [
{
"store_id": 1,
"store1": "store_name",
"POS": [
{
"id_POS": 1,
"POS_name": "name_1",
"purchases": [
{
"id": 1,
"date": "2022_10_05",
"time": "10:00:00"
},
{
"id": 2,
"date": "2022_10_05",
"time": "10:10:00"
}
]
},
{
"id_POS": 2,
"POS_name": "name_2",
"purchases": [
{
"id": 1,
"date": "2022_10_05",
"time": "10:50:00"
},
{
"id": 2,
"date": "2022_10_05",
"time": "11:59:00"
}
]
}
],
"itens": [
{
"id_prod": 4,
"prod_name": "avocado",
"price": 2.5
},
{
"id_prod": 5,
"prod_name": "potato",
"price": 1.5
}
]
}
]
}
Referenced:
group of stores,POS, and itens collection:
{
"group1":{
"stores":[
{
"store_id":1,
"name":"store1",
"POS":[
{"POS":[
{"id_pos":1},
{"id_pos":2}
]}
],
"itens":[
{"id_prod":4},
{"id_prod":5}
]
}
]
}
}
{
"id_pos": 1,
"id_store": 1,
"purchases": [
{
"id": 1,
"date": "2022_10_05",
"time": "10:50:00"
},
{
"id": 2,
"date": "2022_10_05",
"time": "11:59:00"
}
]
}
{
"id_store": 1,
"itens":[{
"id_prod": 4,
"prod_name": "avocado",
"price": 2.5
},
{
"id_prod": 5,
"prod_name": "potato",
"price": 1.5
}]
}

Related

MongoDB query remove bottom 10% extreme values for each specific type of data

Let's say I have a MongoDB storing transaction prices of a few products like this:
[
{
"_id": 1,
"product": "A",
"price": NumberDecimal("1.00")
},
{
"_id": 2,
"product": "A",
"price": NumberDecimal("20.00")
},
{
"_id": 3,
"product": "A",
"price": NumberDecimal("30.00")
},
{
"_id": 4,
"product": "B",
"price": NumberDecimal("10.00")
},
{
"_id": 5,
"product": "B",
"price": NumberDecimal("200.00")
},
{
"_id": 6,
"product": "B",
"price": NumberDecimal("300.00")
}
]
I want to remove bottom 10% of the extreme transaction prices, I do this:
db.collection.aggregate([
{
$bucketAuto: {
groupBy: "$price",
buckets: 10,
output: {
docs: {
$push: "$$ROOT"
}
}
}
},
{
$skip: 1
},
{
$unwind: "$docs"
},
{
$replaceWith: "$docs"
}
])
The outcome is like this:
[
{
"_id": 4,
"price": NumberDecimal("10.00"),
"product": "B"
},
{
"_id": 2,
"price": NumberDecimal("20.00"),
"product": "A"
},
{
"_id": 3,
"price": NumberDecimal("30.00"),
"product": "A"
},
{
"_id": 5,
"price": NumberDecimal("200.00"),
"product": "B"
},
{
"_id": 6,
"price": NumberDecimal("300.00"),
"product": "B"
}
]
The extreme transaction price 1.00 is removed. But I actually want the extreme 10% prices for each product to be removed, so that price 1.00 of product A is removed, and price 10.00 for product B is also removed. Expected result should be:
[
{
"_id": 2,
"price": NumberDecimal("20.00"),
"product": "A"
},
{
"_id": 3,
"price": NumberDecimal("30.00"),
"product": "A"
},
{
"_id": 5,
"price": NumberDecimal("200.00"),
"product": "B"
},
{
"_id": 6,
"price": NumberDecimal("300.00"),
"product": "B"
}
]
How can I achieve this? I have something very close but it is hard coding the product names in the query, which is very wrong:
https://mongoplayground.net/p/ur3Qmr2VJKb

how to insert an object into the players array in mongoDB?

I have the document below and I need to insert an object into the players arrays how to do this with mongoDB
{
"data": {
"createTournament": {
"_id": "6130d9a565aa744f173a824a",
"title": "Jogo de truco",
"description": "",
"status": "PENDING",
"size": 8,
"prizePool": 20,
"currency": "USD",
"type": "Battle",
"entryFee": 1,
"startDate": "2021-09-01",
"endDate": "2021-09-01",
"rounds": [{
"round": 1,
"totalMatches": 4,
"matches": [{
"match": 1,
"players": []
}
]
}]
}
}
}
it will add 3 to array players that array matches has match of 1 and rounds array has round of 1
db.collection('exmaple').updateOne({},
{
$push:{"data.createTournament.rounds.$[outer].matches.$[inner].players":"3"}
},
{ "arrayFilters": [
{ "outer.round": 1 }, // you could change this to choose in which array must be pushed
{ "inner.match":1 } // // you could change this to choose in which array must be pushed
] }
)

MongoDB count values of multible nested documents

My data looks something like that:
[
{
"_id": 1,
"members": [
{
"id": 1,
"name": "name_1",
"assigned_tasks": [
1,
2,
3
]
},
{
"id": 1,
"name": "name_2",
"assigned_tasks": [
1
]
}
],
"tasks": [
{
"id": 1,
"name": "task_1",
},
{
"id": 2,
"name": "task_2",
},
{
"id": 3,
"name": "task_3",
}
]
}
]
I have a collection that represents a "class" which contains a list of members and a list of projects.
Each member can be assigned to multiple projects.
I wanna be able to count the number of members assigned to each of the tasks in the results and add it as a new field like:
[
{
"_id": 1,
"members": [
{
"id": 1,
"name": "name_1",
"assigned_tasks": [
1,
2,
3
]
},
{
"id": 1,
"name": "name_2",
"assigned_tasks": [
1
]
}
],
"tasks": [
{
"id": 1,
"name": "task_1",
"number_of_assigned_members":2
},
{
"id": 2,
"name": "task_2",
"number_of_assigned_members":1
},
{
"id": 3,
"name": "task_3",
"number_of_assigned_members":2
}
]
}
]
How can I create that query?
You can use $map and than $reduce,
$map tasks through object by object check in $reduce on members, if assigned_tasks is available or not, if available then add 1 otherwise 0,
db.collection.aggregate([
{
$addFields: {
tasks: {
$map: {
input: "$tasks",
as: "t",
in: {
$mergeObjects: [
"$$t",
{
number_of_assigned_members: {
$reduce: {
input: "$members",
initialValue: 0,
in: {
$cond: [
{ $in: ["$$t.id", "$$this.assigned_tasks"] },
{ $add: ["$$value", 1] },
"$$value"
]
}
}
}
}
]
}
}
}
}
}
])
Playground

MongoDB - Way to find closest results from arrays inside every document

I want to find closest result from array inside document for every doc, and project it new object using MongoDB. It will be easier to explain what I trying to do by example:
Doc schema:
{
"id": "string",
"name": "string",
"track" : [
{
"time": "number",
"distance": "number"
}
]
}
EXAMPLE:
I want to find closest results for every doc for time equals 4
Input data:
[
{
"id": "1",
"name": "test1",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 3,
"distance": 17
},
{
"time": 4,
"distance": 23
},
{
"time": 6,
"distance": 33
}
]
},
{
"id": "2",
"name": "test2",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 2,
"distance": 12
},
{
"time": 4,
"distance": 26
},
{
"time": 6,
"distance": 32
}
]
},
{
"id": "3",
"name": "test3",
"track" : [
{
"time": 0,
"distance": 0
},
{
"time": 1,
"distance": 5
},
{
"time": 3,
"distance": 12
}
]
}
]
Output data:
[
{
"id": "1",
"result" : {
"time": 4,
"distance": 23
}
},
{
"id": "2",
"result" : {
"time": 4,
"distance": 26
}
},
{
"id": "3",
"result" : {
"time": 3,
"distance": 12
}
}
]
Is it possible to do this using MongoDB?
db.collection.aggregate([
{
"$addFields": {
"tracks": {
"$filter": {
"input": "$track",
"as": "track",
"cond": {
"$lte": [
"$$track.time",
4
]
}
}
}
}
},
{
"$addFields": {
"tracks": {
"$slice": [
"$tracks",
-1
]
}
}
},
{
"$unwind": "$tracks"
},
{
"$project": {
"tracks": 1,
"name": 1
}
}
])
Play
It does below things:
Finds whose track time is <=4 and adds it to an array called items
Then it gets the last element - i.e closer element
Take the element from array - unwind
Projects what is needed.

MongoDB query to nested document returns nothing

Here is a sample product document stored in MongoDB:
[
{
"_id": "....",
"user_id": "....",
"username": "....",
// omitted
"product": {
"description": "A stunningly beautiful page with a constant growth of followers, etc. ❤",
"banner_img": "https://tse3-mm.cn.bing.net/th/id/OIP.jNCbt_c_8vnq7sbWluCVnQHaCG?w=300&h=85&c=7&o=5&pid=1.7",
"niches": "Fashion & Style",
"categories": [
{
"type": "Single",
"pricing": [
{
"time": 6,
"price": 15,
"bio_price": 10
},
{
"time": 12,
"price": 20,
"bio_price": 10
}
]
},
{
"type": "Multiple",
"pricing": [
{
"time": 12,
"price": 30.5,
"bio_price": 15
}
]
},
{
"type": "Story",
"pricing": [
{
"time": 24,
"price": 40,
"bio_price": 20
}
]
}
]
},
"created_at": "2020-01-11T18:19:54.312Z",
"updated_at": "2020-01-11T18:19:54.312Z"
}
],
I'd like to find an account that has a product with Multiple or Story pricing type. My query is as follows:
{
product: {
categories: {
pricing: {
$elemMatch: {
type: { $in: ['Multiple', 'Story'] }
}
}
}
}
}
I'm running this query with lucid-mongo in adonisjs framework.
It should at least return one document but it returns nothing.
I ran the query both in framework and on mongo.exe but not works.
What's wrong with my query?