MongoDB query to nested document returns nothing - mongodb

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?

Related

Remove unwanted key on nested unique keys MongoDB

I have this kind of mongodb document example
"data": {
"2023-02-01": {
"123": {
"price": 100,
},
"234": {
"price": 100,
},
},
"2023-02-02": {
"123": {
"price": 100,
},
"234": {
"price": 100,
},
},
"2023-02-03": {
"123": {
"price": 100,
},
"234": {
"price": 100,
},
},
}
I have list of mapped ID on my aystem, it should be like
ids = [123]
I want to remove the key that not in the list (ids) from the document, started from a specific date (today/"2023-02-02"), the date always updated and so the ID, my expected result is
"data": {
"2023-02-01": {
"123": {
"price": 100,
},
"234": {
"price": 100,
},
},
"2023-02-02": {
"123": {
"price": 100,
},
},
"2023-02-03": {
"123": {
"price": 100,
},
},
}
Could I achieve that on MongoDB aggregation? I'm using pymongo
Following the discussion in comments, if refactoring the schema is an option, you can achieve what you need in very simple query.
db.collection.update({
"date": {
$gte: ISODate("2023-02-02")
}
},
[
{
$set: {
value: {
$filter: {
input: "$value",
as: "v",
cond: {
$in: [
"$$v.key",
[
"123"
]
]
}
}
}
}
}
],
{
multi: true
})
Mongo Playground
The schema I am proposing:
[
{
"date": ISODate("2023-02-01"),
"value": [
{
"key": "123",
"price": 100
},
{
"key": "234",
"price": 100
}
]
},
{
"date": ISODate("2023-02-02"),
"value": [
{
"key": "123",
"price": 100
},
{
"key": "234",
"price": 100
}
]
},
{
"date": ISODate("2023-02-03"),
"value": [
{
"key": "123",
"price": 100
},
{
"key": "234",
"price": 100
}
]
}
]
You can see there is a few things:
avoided using dynamic value as field name
formatted date as proper date objects
avoided highly nesting arrays/objects

Cloudant database search index

I have a Json document in cloudant as:
{
"createdAt": "2022-10-26T09:16:29.472Z",
"user_id": "4499c1c2-7507-4707-b0e4-ec83e2d2f34d",
"_id": "606a4d591031c14a8c48fcb4a9541ff0"
}
{
"createdAt": "2022-10-24T11:15:24.269Z",
"user_id": "c4bdcb54-3d0a-4b6a-a8a9-aa12e45345f3",
"_id": "fb24a15d8fb7cdf12feadac08e7c05dc"
}
{
"createdAt": "2022-10-24T11:08:24.269Z",
"user_id": "06d67681-e2c4-4ed4-b40a-5a2c5e7e6ed9",
"_id": "2d277ec3dd8c33da7642b72722aa93ed"
}
I have created a index json as:
{
"type": "json",
"partitioned": false,
"def": {
"fields": [
{
"createdAt": "asc"
},
{
"user_id": "asc"
}
]
}
}
I have created a index text as:
{
"type": "text",
"partitioned": false,
"def": {
"default_analyzer": "keyword",
"default_field": {},
"selector": {},
"fields": [
{
"_id": "string"
},
{
"createdAt": "string"
},
{
"user_id": "string"
}
],
"index_array_lengths": true
}
}
I have created a selctor cloudant query :
{
"selector": {
"$and": [
{
"createdAt": {
"$exists": true
}
},
{
"user_id": {
"$exists": true
}
}
]
},
"fields": [
"createdAt",
"user_id",
"_id"
],
"sort": [
{
"createdAt": "desc"
}
],
"limit": 10,
"skip": 0
}
This code work fine inside the cloudant ambient.
My problem is in the Search Index.
I created this function code that works,
function (doc) {
index("specialsearch", doc._id);
if(doc.createdAt){
index("createdAt", doc.createdAt, {"store":true})
}
if(doc.user_id){
index("user_id", doc.user_id, {"store":true})
}
}
result by this url:
// https://[user]-bluemix.cloudant.com/[database]/_design/attributes/_search/by_all?q=*:*&counts=["createdAt"]&limit=2
{
"total_rows": 10,
"bookmark": "xxx",
"rows": [
{
"id": "fb24a15d8fb7cdf12feadac08e7c05dc",
"order": [
1.0,
0
],
"fields": {
"createdAt": "2022-10-24T11:15:24.269Z",
"user_id": "c4bdcb54-3d0a-4b6a-a8a9-aa12e45345f3"
}
},
{
"id": "dad431735986bbf41b1fa3b1cd30cd0f",
"order": [
1.0,
0
],
"fields": {
"createdAt": "2022-10-24T11:07:02.138Z",
"user_id": "76f03307-4497-4a19-a647-8097fa288e77"
}
},
{
"id": "2d277ec3dd8c33da7642b72722aa93ed",
"order": [
1.0,
0
],
"fields": {
"createdAt": "2022-10-24T11:08:24.269Z",
"user_id": "06d67681-e2c4-4ed4-b40a-5a2c5e7e6ed9"
}
}
]
}
but it doesn't return the id sorted by date based on the createdAt and user_id keys.
What I would like is to get a list of an organized search with the index of the createdAt and user_id keys without having to indicate the value; a wildcard type search
Where am I wrong?
I have read several posts and guides but I did not understand how to do it.
Thanks for your help.
You say you want to return a list of id, createdAt and user_id, sorted by createdAt and user_id. And that you want all the documents returned.
If that is the case, what you need to do is simply create a MapReduce view of your data that emits the createdAt and user_id fields in that order, i.e. :
function (doc) {
emit([doc.createdAt, doc.user_id], 1);
}
You don't need to include the document id because that comes for free.
You can then query the view by visiting the URL:
https://<URL>/<database>/_design/<ddoc_name>/_view/<view_name>
You will get all the docs like this:
{"total_rows":3,"offset":0,"rows":[
{"id":"2d277ec3dd8c33da7642b72722aa93ed","key":["2022-10-24T11:08:24.269Z","06d67681-e2c4-4ed4-b40a-5a2c5e7e6ed9"],"value":1},
{"id":"fb24a15d8fb7cdf12feadac08e7c05dc","key":["2022-10-24T11:15:24.269Z","c4bdcb54-3d0a-4b6a-a8a9-aa12e45345f3"],"value":1},
{"id":"606a4d591031c14a8c48fcb4a9541ff0","key":["2022-10-26T09:16:29.472Z","4499c1c2-7507-4707-b0e4-ec83e2d2f34d"],"value":1}
]}

Embedded vs. Referenced Documents 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
}]
}

Query nested object in mongodb without key

I have multiple documents saved which look like the one shown below, how would I query against a nested object without the ID to receive the right document?
Here is what I current, but this doesnt work, as I dont have the ID at the start.
db.collection.find({
"details.hardware.id": 5,
})
This is what ive tested and know works but I dont know the ID -
db.collection.find({
"100201.details.hardware.id": 5,
})
Document example -
[
{
"_id": {
"$oid": "6338b69062433c04642d26ca"
},
"100201": {
"broken": true,
"details": {
"build": {
"id": 1018458,
},
"hardware": {
"id": 5,
"model": {
"id": 131,
},
},
"id": 2811302,
"view": {
"id": 781,
}
},
"id": "100201",
"links": [
{
"details": {
"id": 7832,
},
"id": 15012,
},
{
"description": null,
"details": {
"id": 6528,
"model": {
"id": 530
}
},
"id": 15076,
}
],
"ref": false,
}
}
]
any help would be appreciated

Mongodb - Aggregation and Sum for each object

I need to aggregate for each "Product" object from the sales database, and sum "Price" and "Quantity" to make a product classification.
I was able to group by "Products" but I can't sum Price and Quantity to the each object.
{$group: {
_id: '$products.items',
totalprice:{$sum: "$products.items.price"},
}}
Below sample of sales database, where I need to return the sum of the "Price" and "Quantity" fields sold for each "Products".
{
"_id": {
"$oid": "5d753707c0cd851e80da914c"
},
"created_on": {
"$date": {
"$numberLong": "1567962886000"
}
},
"custumer": {
"name": "Teste",
"cep": "teste",
"address": "teste",
"district": "test",
"city": "test",
"numb": "50",
"comple": "test",
"state": "test",
"cpf": "test",
"birth": "30/09/1977",
"email": "test#gmail.com",
"phone": {
"$numberDouble": "1111111111111"
},
"gender": "M",
"portalt": {
"status": "true",
"vendor": "test",
"phone": {
"$numberDouble": "11111111111"
},
"sim": "011111111111",
"salesnumb": "1222222222222222222"
}
},
"payment": {
"method": "Boleto",
"type": "Parcelado",
"installments": "5",
"billing_date": "15"
},
**"products": {
"items": {
"5d515979736802000415a561": {
"item": {
"_id": "5d515979736802000415a561",
"name_produto": "Product 1",
"resumo": "Minutos ilimitados,20GB + 2GB",
"price": "110",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "2"
},
"price": {
"$numberInt": "220"
}
},
"5d515aba736802000415a562": {
"item": {
"_id": "5d515aba736802000415a562",
"name_produto": "Product 2",
"resumo": "Minutos ilimitados,3GB + 1GB",
"price": "80",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "1"
},
"price": {
"$numberInt": "80"
}
},
"5d515dbf736802000415a564": {
"item": {
"_id": "5d515dbf736802000415a564",
"name_produto": "Product 3",
"resumo": "Minutos ilimitados,30GB + 3GB",
"price": "150",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "1"
},
"price": {
"$numberInt": "150"
}
}
},**
"totalItems": {
"$numberInt": "4"
},
"totalPrice": {
"$numberInt": "450"
}
},
"seller": {
"_id": {
"$oid": "5cd086787dc59921bcad94d8"
},
"name": "test"
}
}
I need output something like:
_id:Object
5d515979736802000415a561:{sum_price: 300, sum_quantity: 30 }
5d515aba736802000415a562:{sum_price: 500, sum_quantity: 60 }
5d515dbf736802000415a564:{sum_price: 600, sum_quantity: 70 }
Thanks so much!
So let's go with the OP ask to sum the individual product price and quantity. Stripping away the other fields which are not relevant to the ask, we arrive at something like this:
var r =
[
{
_id:0,
"products": {
"items": {
"5d515979736802000415a561": {
"quantity": 2,
"price": 220,
},
"5d515aba736802000415a562": {
"quantity": 1,
"price": 80
}
}
}
}
, {
_id:1,
"products": {
"items": {
"5d515979736802000415a561": { // deliberately same id as doc above but different quantity and price
"quantity": 3,
"price": 330
},
"5d515aba736802000415a562": { // same
"quantity": 2,
"price": 160
},
"5d515979736802000415ZZZZ": { // different than above; adds "third item"
"quantity": 4,
"price": 200
}
}
}
}
];
Note that the whole inner item field is basically not important, not the least of which it only contains the unit price, not the total price (amount) and quantity per product.
"5d515dbf736802000415a564": {
"item": {
"_id": "5d515dbf736802000415a564",
// etc
So now we employ the $objectToArray to turn the keys into rvals. That gives us something we can $group on, and so here is a solution:
db.foo.aggregate([
{$project: {X: {$objectToArray: "$products.items"}}}
,{$unwind: "$X"}
,{$group: {_id: "$X.k", tot_q: {$sum:"$X.v.quantity"}, tot_amt: {$sum:"$X.v.price"}} }
]);
which given the input above yields:
{ "_id" : "5d515979736802000415ZZZZ", "tot_q" : 4, "tot_amt" : 200 }
{ "_id" : "5d515aba736802000415a562", "tot_q" : 3, "tot_amt" : 240 }
{ "_id" : "5d515979736802000415a561", "tot_q" : 5, "tot_amt" : 550 }