how to query mongodb nested query three level? - json

I have three collections (docs example struct see below :)
my mongodb version is 4.4
section
{
_id: ObjectId('62b131211331e0e9ba284187'),
name: 'name1',
},
{
_id: ObjectId('62b131211331e0e9ba284187'),
name: 'name2',
}
...
2.problems
{
_id: ObjectId('62b13d5f1331e0e9ba2841e6'),
title: 'title1',
score: 10,
section_id: ObjectId('62b131211331e0e9ba284188')
},
{
_id: ObjectId('62b13d5f1331e0e9ba2841e6'),
title: 'title2',
score: 20,
section_id: ObjectId('62b131211331e0e9ba284188')
},
{
_id: ObjectId('62b13d5f1331e0e9ba2841e6'),
title: 'title3',
score: 30,
section_id: ObjectId('62b131211331e0e9ba284188')
}
...
3.choices
{
_id: ObjectId('62b164ae1331e0e9ba284236'),
text: 'text1',
value: 0,
checked: false,
problem_id: ObjectId('62b13d5f1331e0e9ba2841ed')
},
{
_id: ObjectId('62b164ae1331e0e9ba284236'),
text: 'text2',
value: 0,
checked: false,
problem_id: ObjectId('62b13d5f1331e0e9ba2841ed')
},
{
_id: ObjectId('62b164ae1331e0e9ba284236'),
text: 'text3',
value: 0,
checked: false,
problem_id: ObjectId('62b13d5f1331e0e9ba2841ed')
},
...
the relationship of those collections
sections has many problems
problems has many choices
My question is :
Now I have an array of sections's id like below:
[
ObjectId('62b131211331e0e9ba284188'),
ObjectId('62b131211331e0e9ba28418a'),
ObjectId('62b131211331e0e9ba28418c')
]
I want to perform one query get the result like below:
[
{
_id: ObjectId('62b131211331e0e9ba284187'),
name: 'name1',
problems: [
{
_id: ObjectId('62b13d5f1331e0e9ba2841e6'),
title: 'title1',
score: 10,
section_id: ObjectId('62b131211331e0e9ba284188'),
choices: [
{}, // choice doc
]
},
{
_id: ObjectId('62b13d5f1331e0e9ba2841e6'),
title: 'title2',
score: 10,
section_id: ObjectId('62b131211331e0e9ba284188'),
choices: [
{}, // choice doc
]
},
...
]
},
{
_id: ObjectId('62b131211331e0e9ba284187'),
name: 'name1',
problems: [
{},
]
},
{
_id: ObjectId('62b131211331e0e9ba284187'),
name: 'name1',
problems: [
{},
]
}
]
I have try run this query in my mongoexpress but it didn't work:
// match stage (ps: start with sections collection)
{
"_id": {
$in: [
ObjectId('62b131211331e0e9ba284188'),
ObjectId('62b131211331e0e9ba28418a'),
ObjectId('62b131211331e0e9ba28418c')
]
}
// lookup stage
{
from: 'problems',
let: {"sid": "$_id"},
pipeline: [
{
"$match": {
"$expr": {
"$eq": ["$section_id", "$$sid"]
},
},
},
{
"$lookup": {
from: "choices",
let: {"chid": "$_id"},
pipeline: [
{
"$match": {
"$expr": {},
},
},
],
as: "choices"
},
},
],
as: "problems"
}

Related

Grouping after Mongoose aggregation lookup

Actually im new to mongoDB and mongoose, and im tryig to get nested join using three schemas and grouping them.
const company = Schema(
{
title: {type: String, required: true},
}
);
const plans = Schema(
{
companyId: {type: Schema.Types.ObjectId, ref: 'company', required: true},
title: {type: String, required: true},
}
);
const promotions = Schema(
{
planId: {type: Schema.Types.ObjectId, ref: 'plans', required: true},
title: {type: String, required: true},
}
);
I got the below result but separated, and I would like to group it, any help with this point would be appreciated?
[
{
_id: '621c2749ac447abf20a8a263',
title: 'test 1',
plans: {
_id: '621c290ad6bce1084f900b0b',
title: 'test 1',
promotions: {
_id: '621d1187b18de3c35fa3963b',
title: 'test 1',
},
},
},
{
_id: '621c2749ac447abf20a8a263',
title: 'test 2',
plans: {
_id: '621c290ad6bce1084f900b0b',
title: 'test 2',
promotions: {
_id: '621d1187b18de3c35fa3963d',
title: 'test 2',
},
},
},
];
The result that i want to achieve is:
[
{
title: 'company name',
plans: [
{
title:'plan name',
promotions: [
{
title:'promotion name'
}
]
},
...
]
},
...
]
A nested "$lookup" is one way to do it.
db.company.aggregate([
{
// lookup plans matching companies
"$lookup": {
"from": "plans",
"localField": "_id",
"foreignField": "companyId",
"pipeline": [
{
// lookup promotions matching plans
"$lookup": {
"from": "promotions",
"localField": "_id",
"foreignField": "planId",
"as": "promotions"
}
}
],
"as": "plans"
}
},
{
// drop unwanted fields
"$project": {
"_id": 0,
"plans._id": 0,
"plans.companyId": 0,
"plans.promotions._id": 0,
"plans.promotions.planId": 0
}
}
])
Try it on mongoplayground.net.

how to display json in table vuejs

how to display the following json data ?
i have json data like this, and want to display it in table, i use vue-bostrapt .
Previously I tried like this, but it's not perfect.
this my json
[
{
"id":"1",
"name": "KINTIL",
"desc": "Kintil is good",
"location": [
{
"prov": "Jawa Barat",
"city": "Bandung"
},
{
"prov": "Banten",
"city": "Tanggerang"
}
],
"applied": [
{
"item_name": "galian"
},
{
"item_name": "timbunan"
}
],
"exception": [
{
"ex_name": "F001",
"ex_value": "001001"
},
{
"ex_name": "M001",
"ex_value": "002002"
}
]
}
]
and this html
<b-table class="table spacing-table" style="font-size: 13px;" show-empty
:items="inovasi" :fields="fields" :current-page="currentPage" :per-page="0" :filter="filter" >
</b-table>
and this my script
import json from "../static/data.json";
export default {
name: 'tes',
data() {
return {
inovasi:[],
filter: null,
fields: [
{
key: 'id',
label: 'id',
sortable: true
},
{
key: 'name',
label: 'name',
sortable: true
},
{
key: 'location',
label: 'location',
sortable: true
},
{
key: 'applied',
label: 'applied',
sortable: true
},
{ key: 'actions', label: 'Doc' }
],
currentPage: 0,
perPage: 5,
totalItems: 0
}
},
mounted() {
this.inovasi = json;
},
computed:{
},
methods: {
}
}
this result
how to display location and applied , into a single row table ?
thanks in advance for those who have answered :)
thanks
You can do it using formatter like
fields: [
{
key: 'id',
label: 'id',
sortable: true
},
{
key: 'name',
label: 'name',
sortable: true
},
{
key: 'location',
label: 'location',
sortable: true,
formatter: (value, key, item) => {
return value.map(x => 'prov: ' + x.prov + ' city:' + x.city).join(", ")
}
},
{
key: 'applied',
label: 'applied',
sortable: true,
formatter: (value, key, item) => {
return value.map(x => x.item_name).join(", ")
}
},
{ key: 'actions', label: 'Doc' }
],
It will show for the location column this: prov: Jawa Barat city:Bandung, prov: Banten city:Tanggerang and for the applied column this: galian, timbunan

mongodb $lookup has_many association from embedded document

I have a boards collection, a lists collection, and a cards collection. An array of lists is embedded in a board document. I am trying to get an output that looks like this:
{
_id: 1,
title: "a board",
lists: [
{
_id: 1,
title: "a list",
cards: [ { _id: 1, title: "a card", list_id: 1 }, { _id: 2, title: "another card", list_id: 1 } ]
},
...
]
}
I want to nest the cards in the list it belongs to. The card document has a list_id field. I tried this:
db.boards.aggregate([
{ '$match' => { _id: 1 } },
{ '$lookup' => {
from: "cards",
localField: "lists._id",
foreignField: "list_id",
as: "cards"
} },
])
But that resulted in:
{
_id: 1,
title: "a board",
lists: [ { _id: 1, title: "a list" } ],
cards: [ { _id: 1, title: "a card", list_id: 1 }, { _id: 2, title: "another card", list_id: 1 } ]
}
I know that I have to use $unwind to get the result I want, but I can't get it to work
You need one additional aggregation pipeline step to "merge" these two lists and you can achieve it by running $map with embedded $filter. It simply works as a "join" operation on two arrays:
{
$project: {
_id: 1,
title: 1,
lists: {
$map: {
input: "$lists",
as: "list",
in: {
$mergeObjects: [
"$$list",
{
cards: {
$filter: {
input: "$cards",
cond: { $eq: [ "$$this.list_id", "$$list._id" ] }
}
}
}
]
}
}
}
}
}
Mongo Playground

Extjs load combo boxes dynamically using recursive json data

I have set of models and a store as given below.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
'id', 'name', 'total'],
hasMany: {
model: 'Order',
name: 'orders'
},
proxy: {
type: 'rest',
url: 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});
Ext.define('Order', {
extend: 'Ext.data.Model',
fields: [
'id', 'total'],
hasMany: {
model: 'OrderItem',
name: 'orderItems',
associationKey: 'order_items'
},
belongsTo: 'User'
});
Ext.define('OrderItem', {
extend: 'Ext.data.Model',
fields: [
'id', 'price', 'quantity', 'order_id', 'product_id'],
belongsTo: ['Order', {model: 'Product', associationKey: 'product'}]
});
var store = Ext.create('Ext.data.Store', {
model: 'User'
});
And below is the json file which I use to load data.
{
"users": [
{
"id": "123",
"name": "Ed",
"orders": [
{
"id": "50",
"total": "100",
"order_items": [
{
"id" : "20",
"price" : "40",
"quantity": "2",
"product" : {
"id": "1000",
"name": "MacBook Pro"
}
},
{
"id" : "21",
"price" : "20",
"quantity": "3",
"product" : {
"id": "1001",
"name": "iPhone"
}
}
]
}
]
},
{
"id": "124",
"name": "Nisha",
"orders": [
{
"id": "52",
"total": "1004",
"order_items": [
{
"id" : "22",
"price" : "40",
"quantity": "23",
"product" : {
"id": "1002",
"name": "Nokia"
}
},
{
"id" : "23",
"price" : "100",
"quantity": "3",
"product" : {
"id": "1003",
"name": "apple"
}
}
]
}
]
}
]
}
I am loading the user IDs to L1_combo_box as below and according to the user ID the user selects from the L1_combo_box, I need to load order_item ids to L2_combo_box .
For example, I load user ids 123, 124 to L1_combo_box and when user selects 123 from L1 combo box, I need to load 20,21 to L2 combo box. If user selects 124, then I need to load 22,23.
Below is the partially completed code. can anyone help me to complete this?
var searchFormFieldsetItems = [
{
xtype: 'fieldcontainer',
combineErrors: true,
name: 'search_form_fieldset_items',
msgTarget: 'side',
fieldLabel: '',
defaults: {
hideLabel: true
},
items: [{
xtype: 'combo',
name: 'L1_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'remote',
store:store,
listeners: {
change: {
fn: function(combo, value) {
var store1 = 'users/orders/order_items/';//This line is partially completed
L2_combo_box.bindStore(store1);
}
}
}
},{
xtype: 'combo',
name: 'L2_combo_box',
displayField: 'id',
valueField: 'id'
}
]
}
];
For this you need to use select for combobox and inside of select event you need to use loadData() method of store to adding data in second combo.
In this FIDDLE, I have created a demo using your code and put my efforts for showing data in second combo. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('User', {
extend: 'Ext.data.Store',
autoLoad: true,
alias: 'store.user',
fields: ["id", "name", "orders"],
proxy: {
type: 'ajax',
url: 'users.json',
reader: {
type: 'json',
rootProperty: 'users'
}
}
});
Ext.define('Order', {
extend: 'Ext.data.Store',
alias: 'store.order',
field: ["id", "price", "quantity", "product"],
storeId: 'order'
});
Ext.create('Ext.form.Panel', {
title: 'Example Combo',
bodyPadding: 5,
defaults: {
width: 250
},
// The fields
defaultType: 'combo',
items: [{
name: 'L1_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'local',
emptyText: 'Select user',
store: {
type: 'user'
},
listeners: {
select: function (combo, rec) {
var L2_combo_box = combo.up('form').getForm().findField('L2_combo_box'),
order = rec.get('orders') || [],
data = [];
//reset combo value
L2_combo_box.reset();
//If order have multipe data then need use forEach for all data
order.forEach(item => {
data = data.concat(item.order_items);
});
//load data in combo store
Ext.getStore('order').loadData(data);
}
}
}, {
emptyText: 'Select order items',
name: 'L2_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'local',
store: {
type: 'order'
}
}],
renderTo: Ext.getBody()
});
}
});

Sort a store data based on inner JSON field sencha

i have a json in the following format:
{
"collection": [
{
"id": 4,
"tickets": [
{
"price": 40,
},
{
"price": 50,
}
],
},
{
"id": 1,
"tickets": [
{
"price": 10,
},
{
"price": 15,
}
]
},
]
}
STORE:
Ext.define("myProject.store.ABCs", {
extend: "Ext.data.Store",
config: {
model: "myProject.model.ABC",
autoLoad: false,
proxy: {
type: "ajax",
url: '', //myURL
reader: {
type: "json",
rootProperty: "collection", // this is the first collection
},
},
}
});
For this particular JSON i created the models as:
Ext.define("myProject.model.ABC", {
extend: "Ext.data.Model",
config: {
idProperty: "id",
fields:[
{name: "id", type: "int" },
],
hasMany: [
{
model: "myProject.model.XYZ",
name: "tickets",
associationKey: "tickets",
},
],
}
});
And second model as:
Ext.define("myProject.model.XYZ", {
extend: "Ext.data.Model",
config: {
// idProperty: "id",
fields:[
{name: "inner_id", type: "int" },
],
belongsTo: 'myProject.model.ABC'
}
});
This particular code creates a store and populates the models correctly.
var store = Ext.getStore('ABCs');
Now i want to sort this store based on store.tickets().getAt(0).get('price') that is sort the ABC records based on XYZ's first price property.
In the above json. ABC Records will be: [{id:4}, {id:1}]
But since first price in XYZ (40 > 10), i want to sort them and create [{id:1}, {id:4}]
Take a look at the Ext.util.Sorter class, where you can set a sorterFn. See the example at the top of the page - you should be able to simply write the logic for sorting records the way you describe.