I have the following document:
{
"month": 2,
"year": 2019,
"categories": [
{
"title": "Income",
"budget": 5000,
"amount": 2000,
"subcategories": [
{
"title": "Paychecks",
"budget": 4000,
"amount": 1000,
"transactions": [
{
"day": 3,
"amount": 600,
"vendor": "Microsoft",
"memo": "Paycheck 1"
},
{
"day": 10,
"amount": 400,
"vendor": "Google",
"memo": "Paycheck 2"
}
]
},
{
"title": "Other",
"budget": 1000,
"amount": 1000,
"transactions": [
{
"day": 7,
"amount": 600,
"vendor": "Mom",
"memo": "Gift for Baby"
},
{
"day": 19,
"amount": 400,
"vendor": "Amy",
"memo": "Gift for Julie"
}
]
}
]
},
{
"title": "Housing",
"budget": 3000,
"amount": 3000,
"subcategories": [
{
"title": "Rent",
"budget": 2000,
"amount": 2000,
"transactions": [
{
"day": 1,
"amount": 2000,
"vendor": "Homes4Rent",
"memo": "Rent"
}
]
},
{
"title": "Electric",
"budget": 1000,
"amount": 1000,
"transactions": [
{
"day": 14,
"amount": 1000,
"vendor": "Tampa Electric",
"memo": "Electric"
}
]
}
]
}
]}
I need to ensure that the "categories.budget" amount is always equal to the sum of the "categories.subcategories.budget" amounts for that category.
For example, I need to ensure that the budget for "Income" is 5000 because the sum of the budgets for its subcategories ("Paychecks" and "Other") is exactly 5000.
The most desirable solution would be one that can perform the sum and the "categories.budget" field update in a single query but I'm unsure how to accomplish this or if this is even possible. Here's what I've come up with so far:
db.collection.aggregate(
[
{
$match: {
month:2,
year:2019
}
},
{
$unwind: "$categories"
},
{
$unwind: "$categories.subcategories"
},
{
$group: {
_id: {
category: "$categories.title"
},
sum: {
$sum: "$categories.subcategories.budget"
}
}
}
])
Unfortunately, this only seems to be printing out the category budgets instead of summing them. Whichever solution is realized will ultimately be used in various places throughout my application to perform similar operations as well.
Thank you so much and let me know if I need to provide any further information.
Related
Using Elasticsearch I am trying to combine a nested array of objects into one array.
This is what my data looks like:
GET invoices/_search
{
"hits": [
{
"_index": "invoices",
"_id": "1234",
"_score": 1.0,
"_source": {
"id": 1234,
"status": "unpaid",
"total": 15.35,
"payments": [
{
"id": 1981,
"amount": 10,
"date": "2022-02-09T13:00:00+01:00"
},
{
"id": 1982,
"amount": 5.35,
"date": "2022-02-09T13:35:00+01:00"
}
]
}
},
# ... More hits
]
}
I want to only get the payments array of each hit combined into one array, so that it returns something like this:
{
"payments": [
{
"id": 1981,
"amount": 10,
"date": "2022-02-09T13:00:00+01:00"
},
{
"id": 1982,
"amount": 5.35,
"date": "2022-02-09T13:35:00+01:00"
},
{
"id": 5658,
"amount": 3,
"date": "2021-12-19T13:00:00+01:00"
}
]
}
I tried to get this result using nested queries but could not figure it out, the query I used is:
# Query I used:
GET invoices/_search
{
"_source": ["payments"],
"query": {
"nested": {
"path": "payments",
"query": {
"bool": {
"must": [
{
"exists": {
"field": "payments.id"
}
}
]
}
}
}
}
}
# Result:
{
"hits": [
{
"_index": "invoices",
"_id": "545960",
"_score": 1.0,
"_source": {
"payments": [
{
"date": "2022-01-22T15:38:15+01:00",
"amount": 374.5,
"id": 320320
},
{
"date": "2022-01-22T15:30:03+01:00",
"amount": 160.5,
"id": 320316
}
]
}
},
{
"_index": "invoices",
"_id": "545961",
"_score": 1.0,
"_source": {
"payments": [
{
"date": "2022-01-22T15:38:15+01:00",
"amount": 12,
"id": 320350
},
{
"date": "2022-01-22T15:30:03+01:00",
"amount": 60.65,
"id": 320379
}
]
}
}
]
}
The result returns only the payments array but divided over multiple hits. How can I combine those arrays?
How to calculate the sum of confident_score for every individual vendor?
Data stored in the DB:
[
{
"_id": "61cab38891152daf9387c0c7",
"name": "dummy",
"company_email": "abc#mailinator.com",
"brief_msg": "Cillum sed est prae",
"similar_case_ids": [],
"answer_id": [
"61cab38891152daf9387c0c9"
],
"pros_cons": [
{
"vendor_name": "xyzlab",
"score": [
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor F",
"confident_score": 80,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf0f"
},
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor FFF",
"confident_score": 40,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf10"
}
]
},
{
"vendor_name": "abclab",
"score": [
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor B",
"confident_score": 50,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf16"
},
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor BB",
"confident_score": 60,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf17"
}
]
}
]
the query for getting the matching id and grouping objects according to the vendor_name:
aggregate([
{
$match: { _id: id }
},
{
$unwind: {
path: '$pros_cons'
}
},
{
$group: {
_id: '$pros_cons'
}
},
])
};
After query I'm getting this:
[
{
"_id": {
"vendor_name": "abclab",
"score": [
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor B",
"confident_score": 50,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf16"
},
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor BB",
"confident_score": 60,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf17"
}
],
}
},
{
"_id": {
"vendor_name": "xyzlab",
"score": [
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor F",
"confident_score": 80,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf0f"
},
{
"question_id": "61c5b47198b2c5bbf9f6471c",
"title": "Vendor FFF",
"confident_score": 40,
"text": "text1",
"_id": "61cac505caeeeb3cec78bf10"
}
],
}
}
]
Need to calculate sum for (vendor_name:abclab)TOTAL=110 and for (vendor_name:xyzlab)TOTAL=120 INDIVIDUALLY
required output:
[
{
"vendor_name": "abclab",
"totalScore": 110,
"count" : 2
},
{
"vendor_name": "xyzlab",
"totalScore": 120,
"count" : 2
}
]
$match - Filter documents by id.
$unwind - Deconstruct pros_cons array to multiple documents.
$project - Decorate output documents. With $reduce, to create totalScore field by summing confident_score from each element in pros_cons.score array.
db.collection.aggregate([
{
$match: {
_id: "61cab38891152daf9387c0c7"
}
},
{
$unwind: {
path: "$pros_cons"
}
},
{
$project: {
_id: 0,
vendor_name: "$pros_cons.vendor_name",
totalScore: {
$reduce: {
input: "$pros_cons.score",
initialValue: 0,
in: {
$sum: [
"$$value",
"$$this.confident_score"
]
}
}
}
}
}
])
Sample Demo on Mongo Playground
I have a data like this.
"products": [{
"_id": {
"$oid": "5ffd0a8f6273740017cc5fca"
},
"name": "Banana",
"price": 65,
"createdAt": {
"$date": "2021-01-12T02:33:51.648Z"
},
"updatedAt": {
"$date": "2021-01-12T02:33:51.648Z"
},
"quantity": 3
}, {
"_id": {
"$oid": "5ffd09326273740017cc5fb3"
},
"name": "Apple",
"price": 79,
"createdAt": {
"$date": "2021-01-12T02:28:02.412Z"
},
"updatedAt": {
"$date": "2021-01-12T02:28:02.412Z"
},
"quantity": 2
}]
What I'm trying to do is multiply the price over the quantity.
Implementation:
{ $reduce: {
input: '$products', initialValue: 0,
in: { $multiply: ["$products.price",
"$products.quantity"] } }
I'm having an error $multiply only supports numeric types, not array
I have a JSON with documents and each document has a few _childDocuments_ I want to search in the parent and get back the parents and facets on each parent separate
Here is a sample JSON
[{
"id": 1,
"productName": "Ford Explorer",
"_childDocuments_": [{
"id": 6,
"color": "blue",
"price": 1000
},
{
"id": 7,
"color": "red",
"price": 2000
}
]
},
{
"id": 1,
"productName": "Ford F150",
"_childDocuments_": [{
"id": 10,
"color": "blue",
"price": 5000
},
{
"id": 11,
"color": "red",
"price": 6000
}
]
},
{
"id": 2,
"productName": "Toyota Highlander",
"_childDocuments_": [{
"id": 8,
"color": "green",
"price": 1200
},
{
"id": 9,
"color": "red",
"price": 2000
}
]
}
]
I want when I search for Ford I should get back all Fords and in each root document get back facets of the children.
Something like this:
[{
"id": 1,
"productName": "Ford Explorer",
"facets": {
"count": 2,
"prices": {
"buckets": [{
"val": 2000,
"count": 1
},
{
"val": 3000,
"count": 1
}
]
}
}
},
{
"id": 1,
"productName": "Ford F150",
"facets": {
"count": 2,
"prices": {
"buckets": [{
"val": 5000,
"count": 1
},
{
"val": 6000,
"count": 1
}
]
}
}
}
]
This is what I got so far
q={!parent+which=type:parent}&json.facet={ "prices": {
"type": "range",
"field": "price",
"start": 1000,
"end": 1000,
"gap": 1000
}
,
}
But this is only returning facets on all child documents.
Thanks in advance
I am using pivottable to create and display dynamic report and I would like to know is there any way to pivot the data in sub array on the json?
Example data:
<script type="text/javascript">
// This example is the most basic usage of pivot()
var data = [
{
"accountId": "50000X",
"productId": 1,
"name": "PRODUCT A",
"sku": "SKU-A",
"fulfillmentSku": "SKU-A",
"friendlySku": "SKU-A",
"quantityStart": 19524,
"quantityEnd": 18523,
"activity": [
{
"eventType": "Assemby",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": -1
},
{
"eventType": "Deduction",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": -1500
},
{
"eventType": "Received",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": 500
}
]
},
{
"accountId": "50000X",
"productId": 97,
"name": "PRODUCT B",
"sku": "SKU-B",
"fulfillmentSku": null,
"friendlySku": "SKU-B",
"quantityStart": -22,
"quantityEnd": 48,
"activity": [
{
"eventType": "Assemby",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": 60
},
{
"eventType": "Received",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": 10
}
]
},
{
"accountId": "50000X",
"productId": 96,
"name": "PRODUCT C",
"sku": "SKU-C",
"fulfillmentSku": null,
"friendlySku": "SKU-C",
"quantityStart": 2755,
"quantityEnd": 2755,
"activity": []
},
{
"accountId": "50000X",
"productId": 95,
"name": "PRODUCT D",
"sku": "SKU-C",
"fulfillmentSku": null,
"friendlySku": "SKU-C",
"quantityStart": -11,
"quantityEnd": -6,
"activity": [
{
"eventType": "Assemby",
"createdOnUtc": "2018-01-26T00:00:00",
"quantity": 5
}
]
}
];
$(function () {
$("#output").pivot(data,
{
rows: ["productId", "name", "sku", "quantityStart", "quantityEnd"],
cols: ["activity"]
}
);
});
</script>
I would like to pivot the activity data, everything in the activity is grouped and computed.
or do I have to change my json format to get the expected output?
PivotTable.js cannot handle nested arrays like this (see the documentation here with the note about "scalar values not objects") so you will need to restructure your input.