how to use mybatis association to map VO - mybatis

I got problems using association at resultmap.
I think I miss something about association.
There are duplicate rows related to "goods_no" column and "item_no" column.
When I using assoication, they are considered different.
I want to get
like
(product is unique by goodsNo, itemNo)
[
{
"product": {
"goodsNo": "P001",
"itemNo": "1"
},
"applicableCupVOList": [
{
"prmNo": 1,
"cupIssNo": 22
},
{
"prmNo": 1,
"cupIssNo": 23
}
]
},
{
"product": {
"goodsNo": "P001",
"itemNo": "2"
},
"applicableCupVOList": [
{
"prmNo": 1,
"cupIssNo": 24
}
]
}
]
but result is
[
{
"product": {
"goodsNo": "P001",
"itemNo": "1"
},
"applicableCupVOList": [
{
"prmNo": 1,
"cupIssNo": 22
}
]
},
{
"product": {
"goodsNo": "P001",
"itemNo": "1"
},
"applicableCupVOList": [
{
"prmNo": 1,
"cupIssNo": 23
}
]
},
{
"product": {
"goodsNo": "P001",
"itemNo": "2"
},
"applicableCupVOList": [
{
"prmNo": 1,
"cupIssNo": 24
}
]
}
]
how can get result that I want?
xml
I set resultMap like
<resultMap id="ApplicableCupMap" type="com.plateer.ec1.promotion.apply.vo.PrmAplyVO">
<association property="product" autoMapping="true">
<id property="goodsNo" column="goods_no" />
<id property="itemNo" column="item_no" />
</association>
<collection property="applicableCupVOList" ofType="com.plateer.ec1.promotion.apply.vo.ApplicableCupVO" autoMapping="true">
<id property="cpnIssNo" column="cpn_iss_no"/>
</collection>
</resultMap>

Related

How to perform two group bys in one aggregation query in mongoose?

I'm a beginner trying to create an API using express ang mongodb and this is my first time posting a question here, so forgive me if my question sounds stupid.
I have this data:
Restaurants
[
{
"_id": "630c0d5e82d52d0852d34b11",
"name": "Restaurant 1",
"type": "Fine Dining",
"cuisine": "Korean",
},
{
"_id": "630c0d5e82d52d0852d34b12",
"name": "Restaurant 2",
"type": "Fine Dining",
"cuisine": "International",
},
{
"_id": "630c0d5e82d52d0852d34b13",
"name": "Restaurant 3",
"type": "Casual Dining",
"cuisine": "Korean",
},
{
"_id": "630c0d5e82d52d0852d34b14",
"name": "Restaurant 4",
"type": "Casual Dining",
"cuisine": "International",
},
...
]
so what I want to achieve is when I create a GET request to this API endpoint http://localhost:8000/api/v1/restaurants/stats is this:
{
"status": "success",
"data": {
"cuisines": [
{
"_id": "Korean",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "International",
"restaurants": ["630c0d5e82d52d0852d34b12", "630c0d5e82d52d0852d34b14"],
"quantity": 2
}
],
"type": [
{
"_id": "Casual Dining",
"restaurants": ["630c0d5e82d52d0852d34b14", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "Fine Dining",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b12"],
"quantity": 2
}
]
}
}
This is what I have tried so far
restaurantController.js
...
exports.getRestaurantStats = async (req, res) => {
const cuisines = await Restaurant.aggregate([
{
$group: {
_id: '$cuisine',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
},
]);
res.status(200).json({
status: 'success',
data: {
cuisines,
},
});
};
...
restaurantRoutes.js
...
router.route('/stats').get(restaurantController.getRestaurantStats);
...
The result for calling this endpoint http://localhost:8000/api/v1/restaurants/stats
{
"status": "success",
"data": {
"cuisines": [
{
"_id": "Korean",
"restaurants": ["630c0d5e82d52d0852d34b11", "630c0d5e82d52d0852d34b13"],
"quantity": 2
},
{
"_id": "International",
"restaurants": ["630c0d5e82d52d0852d34b12", "630c0d5e82d52d0852d34b14"],
"quantity": 2
}
]
}
But when I add this another group by
...
$group: {
_id: '$type',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
...
to restaurantController.js
...
exports.getRestaurantStats = async (req, res) => {
const cuisines = await Restaurant.aggregate([
{
$group: {
_id: '$cuisine',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
},
$group: {
_id: '$type',
restaurants: { $push: '$_id' },
quantity: { $sum: 1 },
}
},
]);
res.status(200).json({
status: 'success',
data: {
cuisines,
},
});
};
...
the result is different. Its seems like it overwrote the first group by in the pipeline.

Mongoose - Update multi objects inside an array by ID

Firstly, sorry for my bad English.
Secondly, I want to ask, how to multi-update my document.
I have a row structure like this:
Data Model
[
{
"id": '00001',
"exp": '192',
"items": [
{ "qty": 23, "ID": ObjectId("kieryu35261twerts73940djr") },
{ "qty": 77, "ID": ObjectId("1240a1ffuw33dbcv6ut8888zz") },
{ "qty": 1, "ID": ObjectId("5600r0e0rr67cbd60a1234y5") },
{ "qty": 5, "ID": ObjectId("32bbd0e0rr92cdb60a4386c7") }
],
"stats": [
{ "strenght": 1, "ID": ObjectId("3eruskdjfhrutiwo4059yuol3") },
{ "strenght": 2, "ID": ObjectId("3jdks0d9r2seifldvjmw0km2e") },
{ "strenght": 1, "ID": ObjectId("aslkdnasklnc2112uhnsjssad") },
{ "strenght": 5, "ID": ObjectId("1230msafmlklkmasfmcio3kms") }
]
},
{
"id": '00002',
"exp": '100',
"items": [
{ "strenght": 10, "ID": ObjectId("21312kn3kaklmasklcklasmck") },
{ "strenght": 10, "ID": ObjectId("kldsafklsajdfklmsadlkaskl") }
],
"stats": [
{ "strenght": 9, "ID": ObjectId("aslkclkamiior2oinrkl2adsa") },
{ "strenght": 0, "ID": ObjectId("asdoasjdosmdkl123123kmnsd") }
]
}
]
I want to update one document row by finding the id of the document, and multi-deep elements by ID too. Like this:
{
"id": '00001',
"exp": '555',
"items": [
{ "qty": 44, "ID": ObjectId("kieryu35261twerts73940djr") },
{ "qty": 55, "ID": ObjectId("1240a1ffuw33dbcv6ut8888zz") },
{ "qty": 66, "ID": ObjectId("5600r0e0rr67cbd60a1234y5") },
{ "qty": 77, "ID": ObjectId("32bbd0e0rr92cdb60a4386c7") }
],
"stats": [
{ "strenght": 10, "ID": ObjectId("3eruskdjfhrutiwo4059yuol3") },
{ "strenght": 20, "ID": ObjectId("3jdks0d9r2seifldvjmw0km2e") },
{ "strenght": 12, "ID": ObjectId("aslkdnasklnc2112uhnsjssad") },
{ "strenght": 54, "ID": ObjectId("1230msafmlklkmasfmcio3kms") }
]
}
And last, just for information, I do before this:
await DataModel.findOneAndUpdate(
{
"id" : idvariable // == 00001
},
{
"$set" : {
"exp" : 555,
"items": {
//update qty == 44 where ID == kieryu35261twerts73940djr
//update qty == 55 where ID == 1240a1ffuw33dbcv6ut8888zz
//update qty == 66 where ID == 5600r0e0rr67cbd60a1234y5
//update qty == 77 where ID == 32bbd0e0rr92cdb60a4386c7
},
"stats": {
//update strenght == 10 where ID == 3eruskdjfhrutiwo4059yuol3
//update strenght == 20 where ID == 3jdks0d9r2seifldvjmw0km2e
//update strenght == 12 where ID == aslkdnasklnc2112uhnsjssad
//update strenght == 54 where ID == 1230msafmlklkmasfmcio3kms
}
}
}
)
Please, I don't know how to update it with a single query update, or other technique. Thank you.
Possible, but a bit long query.
Working on the Update with Aggregation Pipeline,
$map - Iterate the items in the array and return a new array.
$switch - Switch-case (statement) to match the ID of the current iterated document and update the document if matched. If all the case conditions are failed to match, remain the existing document.
db.collection.update({
"id": idvariable// == 00001
},
[
{
"$set": {
"exp": 555,
"items": {
$map: {
input: "$items",
in: {
$switch: {
branches: [
{
case: {
$eq: [
"$$this.ID",
"kieryu35261twerts73940djr"
]
},
then: {
$mergeObjects: [
"$$this",
{
qty: 44
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"1240a1ffuw33dbcv6ut8888zz"
]
},
then: {
$mergeObjects: [
"$$this",
{
qty: 55
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"5600r0e0rr67cbd60a1234y5"
]
},
then: {
$mergeObjects: [
"$$this",
{
qty: 66
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"32bbd0e0rr92cdb60a4386c7"
]
},
then: {
$mergeObjects: [
"$$this",
{
qty: 77
}
]
}
}
],
default: "$$this"
}
}
}
},
"stats": {
$map: {
input: "$stats",
in: {
$switch: {
branches: [
{
case: {
$eq: [
"$$this.ID",
"3eruskdjfhrutiwo4059yuol3"
]
},
then: {
$mergeObjects: [
"$$this",
{
strenght: 10
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"3jdks0d9r2seifldvjmw0km2e"
]
},
then: {
$mergeObjects: [
"$$this",
{
strenght: 20
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"aslkdnasklnc2112uhnsjssad"
]
},
then: {
$mergeObjects: [
"$$this",
{
strenght: 12
}
]
}
},
{
case: {
$eq: [
"$$this.ID",
"1230msafmlklkmasfmcio3kms"
]
},
then: {
$mergeObjects: [
"$$this",
{
strenght: 54
}
]
}
}
],
default: "$$this"
}
}
}
}
}
}
])
For the items and stats with ID to be updated, make sure that you need to parse as ObjectId [Note that Mongo Playground doesn't recognize your provided IDs, I manually change the dataset for those IDs as string but the concept for the update is the same].
Sample Mongo Playground

Mongoose not updating multiple matches

[
{
"id": 1,
"items": [
{
id: 15,
score: 10
},
{
id: 14,
score: 100
},
{
id: 12,
score: 1
}
]
},
{
"id": 2,
"items": []
}
]
Now, I try to update items whose id is 14,15 & used the following query.
db.collection.update({
"items.id": {
$in: [
14,
15
]
}
},
{
$set: {
"items.$.score": 444
}
},
{
multi: true
}
)
but it updated only the first match in items that is that is id with 15, what can be wrong?
[
{
"_id": ObjectId("5a934e000102030405000000"),
"id": 1,
"items": [
{
"id": 15,
"score": 444
},
{
"id": 14,
"score": 100
},
{
"id": 12,
"score": 1
}
]
},
{
"_id": ObjectId("5a934e000102030405000001"),
"id": 2,
"items": []
}
]
Use arrayFilters with targeted array elements:
here is the doc
db.collection.update({
"id": 1
},
{
"$set": {
"items.$[ele].score": 20
}
},
{
arrayFilters: [
{
"ele.id": {
"$in": [
15,
14
]
}
}
]
})
see play ground code https://mongoplayground.net/p/cdgu1aqLwsI
You can do it with Positional identifiers $[]
db.collection.update({
"items.id": {
$in: [
14,
15
]
}
},
{
$set: {
"items.$[element].score": 444
}
},
{
arrayFilters: [
{
"element.id": {
$in: [
14,
15
]
}
}
],
multi: true
})
try it here

Project multiple documents with different key nodes for subdocuments

I have two documents as shown. Their common factor is a node in the subdocument (type,veg_type). I have also added the same common node to each individual document (udf_type, udf_veg_type).One is a legacy data (with key node veggies) and another is new data (with key node vegetables).
How do I project the combined data of vegetables and veggies(in key node vegs) without the type and veg_type nodes? I use user_id for matching.
Intended Output
{
"user_id": 31,
"veggies": [
{
"udf_type": "green_vegetables",
"tot": 28560,
"itms": [
{
"num": 1,
"itm_det": {
"name": "spinach",
"qty": 18
}
}
],
"chksum": "d1583afab3a04f4b32589cfa64392765n78782ff60a0e0dc24b295868083"
},
{
"udf_type": "vegetables",
"tot": 2860,
"itms": [
{
"num": 1,
"itm_det": {
"name": "onion",
"qty": 1
}
}
],
"chksum": "e497c7b288e50e3be4c6bc676e4c849e4n5645n64a2d77748e185d7a1bce8c"
},
{
"udf_veg_type": "green_vegetables",
"tot": 2352000,
"itms": [
{
"num": 1,
"itm_det": {
"name": "kale",
"qty": 18
}
}
],
"chksum": "87b239cd9b39baa48b4564b5754009a131f542622ba018f37cd1fdb5"
}
]
}
{
"_id" : ObjectId("1"),
"user_id": 31,
"veggies": [
{
"type": "green_vegetables",
"desc": [
{
"udf_type": "green_vegetables",
"tot": 28560,
"itms": [
{
"num": 1,
"itm_det": {
"name": "spinach",
"qty": 18
}
}
],
"chksum": "d1583afab3a04f4b32589cfa64392765n78782ff60a0e0dc24b295868083"
}
]
},
{
"type": "vegetables",
"desc": [
{
"udf_type": "vegetables",
"tot": 2860,
"itms": [
{
"num": 1,
"itm_det": {
"name": "onion",
"qty": 1
}
}
],
"chksum": "e497c7b288e50e3be4c6bc676e4c849e4n5645n64a2d77748e185d7a1bce8c"
}
]
}
]
}
{
"_id" : ObjectId("2"),
"user_id": 31,
"vegetables": [
{
"veg_type": "green_vegetables",
"desc": [
{
"udf_veg_type": "green_vegetables",
"tot": 2352000,
"itms": [
{
"num": 1,
"itm_det": {
"name": "kale",
"qty": 18
}
}
],
"chksum": "87b239cd9b39baa48b4564b5754009a131f542622ba018f37cd1fdb5"
}
]
}
]
}
Assuming that the desc arrays always have just one item, try this:
db.collection.aggregate([
{
$match: {
"user_id": 31 // change this into the user_id variable
}
},
{
$group: {
_id: "$user_id",
veggies: {
$max: "$veggies"
},
vegetables: {
$max: "$vegetables"
}
}
},
{
$project: {
"user_id": "$_id",
"veggies": {
$concatArrays: [
{
$cond: [
"$veggies",
{
$map: {
input: "$veggies",
in: {
$arrayElemAt: [
"$$this.desc",
0
]
}
}
},
[]
]
},
{
$cond: [
"$vegetables",
{
$map: {
input: "$vegetables",
in: {
$arrayElemAt: [
"$$this.desc",
0
]
}
}
},
[]
]
}
]
}
}
}
])

Mongo request slow

I'm trying Mongo with a million enties. My request is really slow.
Do you have any ideas to optimize it ?
db.financial_transaction.runCommand({
"aggregate": "financial_transaction",
"pipeline": [ {
"$match": {
"transaction_type": { "$in": [ 1, 2 ] },
"created_at": { "$gte": new ISODate("2016-03-13T00:00:00+01:00"), "$lte": new ISODate("2017-12-13T23:59:00+01:00") },
"type": { "$in": [ "A", "C", "E" ] },
"sid": { "$in": [ 1, 3, 7, 9, 11, 13 ] },
"context": { "$in": [ "CL", "RE" ] } }
}, {
"$group": { "_id": { "paymentType": "$payment_type",
"paymentMethod": "$payment_method",
"responseCode": "$response_code",
"reasonCode": "$reason_code"
},
"count": { "$sum": 1 }, "total_amount": { "$sum": "$requested_amount" } } }, { "$sort": { "count": -1 } } ]
});
Indexes:
_id_
idx_context
idx_payment_method
idx_response_code
idx_reason_code
idx_created_at
idx_transaction_type
idc_payment_method_created_at_transaction_type_origin_auth_system
idx_created_at_context_transaction_type
idx_updated_at
I made a gist with the explain result: https://gist.github.com/sanchobouillant/bd59403242ebb1ec45582dff74b457a2