Help me to match in single embedded document of both conditions.
db.inventory.insertOne([
... { "item": "journal", "instock": [ { "warehouse": "A", "qty": 5 }, { "warehouse": "C", "qty": 15 } ] },
... { "item": "notebook", "instock": [ { "warehouse": "C", "qty": 5 } ] },
... { "item": "paper", "instock": [ { "warehouse": "A", "qty": 60 }, { "warehouse": "B", "qty": 15 } ] },
... { "item": "planner", "instock": [ { "warehouse": "A", "qty": 40 }, { "warehouse": "B", "qty": 5 } ] },
... { "item": "postcard", "instock": [ { "warehouse": "B","qty": 15 }, { "warehouse": "C", "qty": 35 } ] }
... ])
Expected to return single document which match exactly as queried but returns two.
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
{ "_id" : ObjectId("63061a1bb87c1278047a2717"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("63061a1bb87c1278047a271a"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
You need to perform the following query:
db.inventory.find({
instock: { $elemMatch: { qty: 5, warehouse: 'A' } }
});
Documentation for reference: https://www.mongodb.com/docs/v5.0/tutorial/query-array-of-documents/#a-single-nested-document-meets-multiple-query-conditions-on-nested-fields
Related
I need to pass the following array as query paramsin wiremock.Is there any possibility of doing that?
"Person": [
{
"name": "AAA",
"age": "20"
},
{
"name": "BBB",
"age": "26"
}
]
I have tried
"bodyPatterns" : [
{
"matchesJsonPath" : "$[?(#.Person.size() >= 2)]"
}
]
and
"bodyPatterns" : [
{
"matchesJsonPath" : "$.Person.name"
},
{
"matchesJsonPath" : "$.Person.age"
}
]
If these are the following nested documents
[
{
"_id": 5,
"name": "Wilburn Spiess",
"scores": [
{
"score": 44.87186330181261,
"type": "exam"
},
{
"score": 25.72395114668016,
"type": "quiz"
},
{
"score": 63.42288310628662,
"type": "homework"
}
]
},
{
"_id": 6,
"name": "Jenette Flanders",
"scores": [
{
"score": 37.32285459166097,
"type": "exam"
},
{
"score": 28.32634976913737,
"type": "quiz"
},
{
"score": 81.57115318686338,
"type": "homework"
}
]
},
{
"_id": 7,
"name": "Salena Olmos",
"scores": [
{
"score": 90.37826509157176,
"type": "exam"
},
{
"score": 42.48780666956811,
"type": "quiz"
},
{
"score": 96.52986171633331,
"type": "homework"
}
]
}
]
I need to access the score part 'type' = exam.
Can somebody help me with this?
If you're asking for a python program to access the score, you can print them out like:
collection = mongo_connection['db']['collection']
documents = collection.find({})
for doc in documents:
for score in doc['scores']:
if score['type'] == 'exam':
print(f'Score: {score["score"]}')
If you are trying to retrieve only the scores and ignore the rest, I'd do an $unwind on the scores, $match on the type, and then project the fields you want (or not).
db.test.aggregate([
{
$unwind: '$scores'
},
{
$match: {
'scores.type': 'exam'
}
},
{
$project: {
'name': '$name',
'score': '$scores.score'
}
}
])
This would output:
{
"_id" : 5,
"name" : "Wilburn Spiess",
"score" : 44.8718633018126
},
{
"_id" : 6,
"name" : "Jenette Flanders",
"score" : 37.322854591661
},
{
"_id" : 7,
"name" : "Salena Olmos",
"score" : 90.3782650915718
}
I get two different files with stock information which I would like to join into one file while summing the data up, based on "pid".
payloadA
{
"order": [
{
"pid": "a",
"instock": "2"
},
{
"pid": "b",
"instock": "2"
},
{
"pid": "c",
"instock": "2"
}
]
}
payloadB
{
"order": [
{
"pid": "c",
"instock": "2"
},
{
"pid": "d",
"instock": "2"
}
]
}
Result
payloadA
{
"order": [
{
"pid": "a",
"instock": "2"
},
{
"pid": "b",
"instock": "2"
},
{
"pid": "c",
"instock": "4"
},
{
"pid": "c",
"instock": "2"
}
]
}
But what I'm struggeling with are the edge cases:
pids might be in both or as well in only one of the datasets
payloadB might be empty
{
"order": []
}
You can try the following DataWeave expression:
%dw 2.0
output application/json
import * from dw::core::Arrays
var payloadA = {
"order": [
{
"pid": "a",
"instock": "2"
},
{
"pid": "b",
"instock": "2"
},
{
"pid": "c",
"instock": "2"
}
]
}
var payloadB = {
"order": [
{
"pid": "c",
"instock": "2"
},
{
"pid": "d",
"instock": "2"
}
]
}
---
"order": outerJoin(payloadA.order, payloadB.order, (itemA) -> itemA.pid, (itemB) -> itemB.pid) map (item, index) -> {
"pid": item.l.pid default item.r.pid,
"instock": (item.l.instock default 0) + (item.r.instock default 0)
}
Output:
{
"order": [
{
"pid": "a",
"instock": 2
},
{
"pid": "b",
"instock": 2
},
{
"pid": "c",
"instock": 4
},
{
"pid": "d",
"instock": 2
}
]
}
My book collection looks like this:
{
"book": {
"title": "Book1",
"author": "Tom"
},
"quantity": 3
},
{
"book": {
"title": "Book2",
"author": "Tom"
},
"quantity": 4
},
{
"book": {
"title": "Book3",
"author": "Dick"
},
"quantity": 9
},
{
"book": {
"title": "Book4",
"author": "Harry"
},
"quantity": 6
},
{
"book": {
"title": "Book5",
"author": "Chris"
},
"quantity": 7
},
{
"book": {
"title": "Book6",
"author": "Dick"
},
"quantity": 10
}
This collection has book documents with title, author and quantity.
I want help in coming up with aggregation which would output the array of authors with their books and quantity. Example - Tom has authored "Book1" and "Book2", "Dick" has authored "Book6" and "Book3".
authors: [
{
"name": "Tom",
"books": [
{
"title": "Book1",
"quantity": "3"
},
{
"title": "Book2",
"quantity": "4"
}
]
},
{
"name": "Dick",
"books": [
{
"title": "Book6",
"quantity": "10"
},
{
"title": "Book3",
"quantity": "9"
}
]
},
{
"name": "Harry",
"books": [
{
"title": "Book4",
"quantity": "6"
}
]
}
]
Try this aggregation:
db.collection.aggregate([{
$group: {
_id: "$book.author",
books: {
$push: {
title: "$book.title",
quantity: "$quantity"
}
}
}},{
$project: {
"name": "$_id",
"books": 1,
"_id": 0
}}])
I tried it on mongo playground:
https://mongoplayground.net/p/m-QbX-uzkkt
Try as below:
db.collection.aggregate([
{
$group: {
_id: "$book.author",
books: { $push: { "title": "$book.title", "quantity": "$quantity"} }
},
}
])
Output will be
/* 1 */
{
"_id" : "Chris",
"books" : [
{
"title" : "Book5",
"quantity" : 7
}
]
},
/* 2 */
{
"_id" : "Harry",
"books" : [
{
"title" : "Book4",
"quantity" : 6
}
]
},
/* 3 */
{
"_id" : "Dick",
"books" : [
{
"title" : "Book3",
"quantity" : 9
},
{
"title" : "Book6",
"quantity" : 10
}
]
},
/* 4 */
{
"_id" : "Tom",
"books" : [
{
"title" : "Book1",
"quantity" : 3
},
{
"title" : "Book2",
"quantity" : 4
}
]
}
I have documents with subdocuments where the field "stars" in the subdocuments have either "1" or "0". I want to count them at the document level based on those values in the field "stars".
This is how the current document looks like:
{
"name": "Hotel A",
"category": "hotel",
"reviews": [
{
"title": "A",
"stars": 1
},
{
"title": "B",
"stars": 1
},
{
"title": "C",
"stars": 0
}
],
"total_reviews": 3
},{
"name": "Hotel B",
"category": "hotel",
"reviews": [
{
"title": "A",
"stars": 1
},
{
"title": "B",
"stars": 1
},
{
"title": "C",
"stars": 0
},
{
"title": "D",
"stars": 0
},
{
"title": "E",
"stars": 1
},
{
"title": "F",
"stars": 0
}
],
"total_reviews": 6
}
And this is the expected output:
{
"name": "Hotel A",
"category": "hotel",
"reviews": [
{
"title": "A",
"stars": 1
},
{
"title": "B",
"stars": 1
},
{
"title": "C",
"stars": 0
}
],
"positive_reviews": 2,
"negative_reviews": 1,
"total_reviews": 3
},{
"name": "Hotel B",
"category": "hotel",
"reviews": [
{
"title": "A",
"stars": 1
},
{
"title": "B",
"stars": 1
},
{
"title": "C",
"stars": 0
},
{
"title": "D",
"stars": 0
},
{
"title": "E",
"stars": 1
},
{
"title": "F",
"stars": 0
}
],
"positive_reviews": 3,
"negative_reviews": 3,
"total_reviews": 6
}
By adding two new fields: "positive_reviews" if {"reviews.stars":1} and "negative_reviews" if {"reviews.stars":0} with the count values
Try as below:
db.collection.aggregate([
{
$project: {
"_id" : 1,
"name" : 1,
"category" : 1,
"reviews" : 1,
"positive_reviews":
{
$reduce:
{
input: "$reviews",
initialValue: 0,
in: {
$add: ["$$value", { $cond:[{ $eq: ["$$this.stars", 1]} , 1, 0 ] } ]
}
}
},
"negative_reviews":
{
$reduce:
{
input: "$reviews",
initialValue: 0,
in: {
$add: ["$$value", { $cond:[{ $eq: ["$$this.stars", 0]} , 1, 0 ] } ]
}
}
},
"total_reviews": { $size: "$reviews"}
}
}
])
Result Response:
/* 1 createdAt:12/04/2019, 18:24:50*/
{
"_id" : ObjectId("5cb08a9a952e3a179190d996"),
"name" : "Hotel A",
"category" : "hotel",
"reviews" : [
{
"title" : "A",
"stars" : 1
},
{
"title" : "B",
"stars" : 1
},
{
"title" : "C",
"stars" : 0
}
],
"positive_reviews" : 2,
"negative_reviews" : 1,
"total_reviews" : NumberInt(3)
},
/* 2 createdAt:12/04/2019, 18:24:50*/
{
"_id" : ObjectId("5cb08a9a952e3a179190d997"),
"name" : "Hotel B",
"category" : "hotel",
"reviews" : [
{
"title" : "A",
"stars" : 1
},
{
"title" : "B",
"stars" : 1
},
{
"title" : "C",
"stars" : 0
},
{
"title" : "D",
"stars" : 0
},
{
"title" : "E",
"stars" : 1
},
{
"title" : "F",
"stars" : 0
}
],
"positive_reviews" : 3,
"negative_reviews" : 3,
"total_reviews" : NumberInt(6)
}