Query all array element is in another array - mongodb

I would like to query documents from a collection where all elements in an array match a condition: both the name field and the quantity should be in and above the minQuantity in the "currentStatus" array.
In this example, I would like to retrieve the documents _id : 1 and 4
Collection = [
{
_id: 1,
conditions: [ {name: 'product1', minQuantity: 30},
{name: 'product2', minQuantity: 10} ]
},
{
_id: 2,
conditions: [ {name: 'product1', minQuantity: 50},
{name: 'product2', minQuantity: 10} ]
},
{
_id: 3,
conditions: [ {name: 'product1', minQuantity: 10},
{name: 'product2', minQuantity: 10},
{name: 'product3', minQuantity: 10} ]
}
{
_id: 4,
conditions: [ {name: 'product1', minQuantity: 10} ]
}
]
currentStatus = [
{name: 'product1', currentQuantity: 40},
{name: 'product2', currentQuantity: 20},
]

Related

MongoDB - How to get specified values of an array in a document

Here is the document
{
'_id': ObjectId('61a4262a53ddaa8b93374613'),
'userid': 'renyi',
'data1': [{'a': 1}, 1, 2, 3],
'data2': [{'c': 1}, {'b': 2}, {'c': 3}, {'c': 2}],
'data': {'0': {'a': 1}}
}
With this
coll.find_one({'userid':'renyi','data2.c':1},{'_id':0,"data2.$":1})
I can get
{'data2': [{'c': 1}]}
But how to get
{'data2': [{'c': 1},{'c': 2}]}
You can use $filter to filter the element within the array in projection.
db.collection.find({
"userid": "renyi",
"data2.c": {
$in: [
1,
2
]
}
},
{
"_id": 0,
"data2": {
$filter: {
input: "$data2",
cond: {
$in: [
"$$this.c",
[
1,
2
]
]
}
}
}
})
Sample Mongo Playground

MongoDB $expr compare field in array

{
name: 'product A',
min_price: 5,
max_price: 15,
stores: [
{name: 'A', price: 6},
{name: 'B', price: 4}
]
},
{
name: 'product B',
min_price: 9,
max_price: 14,
stores: [
{name: 'C', price: 12},
{name: 'B', price: 10}
]
}
How can I find product have store's price $lt min_price?
I tried:
{$expr: { $lt: [ "$min_price", "$stores.price"] }}
Seems like I am doing it wrong!
You're close, you just need to add $min into the batch:
{$expr: { $lt: [ "$min_price", {$min: "$stores.price"} ] }}

How to do mongodb inner join with nested array?

Warehouses schema:
{_id: 1, name: 'A'}
{_id: 2, name: 'B'}
{_id: 3, name: 'C'}
Stocks schema:
{_id: 11, productId: 1, instock: [{warehouse: 'A', qty: 20}, {warehouse: 'B', qty: 5}, {warehouse: 'C', qty: 8}]
{_id: 12, productId: 2, instock: [{warehouse: 'A', qty: 30}]
I am new to MongoDB, but will like to have one row per record to show products' available qty in each of A,B,C warehouses:
Desired array output:
instock: [
{_id: 11, productId: 1, warehouse: 'A', qty: 20},
{_id: 11, productId: 1, warehouse: 'B', qty: 5},
{_id: 11, productId: 1, warehouse: 'C', qty: 8},
{_id: 12, productId: 2, warehouse: 'A', qty: 30},
{_id: 12, productId: 2, warehouse: 'B', qty: 0},
{_id: 12, productId: 2, warehouse: 'C', qty: 0}
]
I read about $lookup, $unwind, $project, and tried something like below but no where near to what I want:
Warehouse.aggregate([
{
$lookup:
{
from: "stocks",
pipeline: [
{ $project: { _id: 0, instock: {qty: 1, warehouse: 1} }},
{ $replaceRoot: { newRoot: { newStock : '$instock' } } }
],
as: "instock"
}
} ,
]);
hi, Anothony Winzlet, your advise works partially, for example:
{_id: 12, productId: 2, instock: [{warehouse: 'A', qty: 30}]
From your solution:
Result show only for warehouse A:
[{_id: 12, productId: 2, warehouse: 'A', qty: 30}]
Can I get for warehouse B & C as well? (will default qty to 0 if not defined)
[{_id: 12, productId: 2, warehouse: 'A', qty: 30},
{_id: 12, productId: 2, warehouse: 'B', qty: 0},
{_id: 12, productId: 2, warehouse: 'C', qty: 0}]
Not sure if above is possible to achieve ... thank you
Solution from Anthony Winzlet:
Warehouse.aggregate([
{ "$unwind": "$instock" },
{ "$replaceRoot": { "newRoot": { "$mergeObjects": ["$$ROOT", "$instock"] } }},
{ "$project": { "instock": 0 } }
])

MongoDB transforming data using aggregation

I have the following data in a collection.
[
{name: "a", status: 1},
{name: "a", status: 2},
{name: "a", status: 3},
{name: "b", status: 1},
{name: "b", status: 4},
{name: "c", status: 1},
{name: "c", status: 1},
{name: "c", status: 5}
]
I want it to be transformed as:
{
names: ["a", "b", "c"],
statuses: [1, 2, 3, 4, 5],
count: [
[1, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[2, 0, 0, 0, 1]
]
}
Explanation:
names will have the unique list of name attribute
statuses will have the unique list of status attribute
Count contains array of count of status per name
For example the first count array is [1, 1, 1, 0, 0]
Which means:
There is only one status:1 for the name a
There is only one status:2 for the name a and so on..
If you take the 3rd array [2, 0, 0, 0, 1]
The name c has status:1 two times
There is no 2 or 3 or 4 but it has one 5
Can you suggest the corresponding aggregation function or equivalent?
Edit:
I just have this so far:
db.collection1.aggregate([
{
$group: {
_id: {environment: "$name", status: "$status"},
count:{$sum: 1}
}
}
])
Thank you

Get chain of nested documents using MongoDB aggregation framework

Suppose there is a document, that contains an array of documents each of which in turn contains an array of documents, like
{_id: 1, level1: [
{_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
{_id: 11, level2: [
{_id: 103},
{_id: 104},
{_id: 105},
]},
{_id: 12, level2: [
{_id: 106},
{_id: 107},
{_id: 108},
]}
]}
and there is an _id = 101 of some inner (third level) document, that I want to search for. I would like to get the inner document and all the enclosing documents in one result, i.e.
{
doc1: {_id: 1, level1: [
{_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
{_id: 11, level2: [
{_id: 103},
{_id: 104},
{_id: 105},
]},
{_id: 12, level2: [
{_id: 106},
{_id: 107},
{_id: 108},
]}
]},
doc2: {_id: 10, level2: [
{_id: 100},
{_id: 101},
{_id: 102},
]},
doc3: {_id: 101}
}
Is it possible to achieve this using the Aggregation Framework?