mongodb aggregation - setting the contents of array as input, while storing sibling keys - mongodb-query

I'm in the middle of an aggregation pipeline when I have the following data passed from the previous step as input to a "count all leaves in all branches/trees/forests" as indicated in this question: Need guidance on mongo aggregate lookup to count subnodes in all child nodes for each node
{
forest_ranger: "bob",
some_other_data: {},
forests: [
{
forest_id: 'forestA',
trees: [
{
tree_id: 'treeA',
branches: [
{
branch_id: 'branchA',
}
]
}
]
}
],
}
I have that all working properly, but only if I'm reading directly from a collection.
My question is - how can I
a) save forest_ranger and some_other_data "for later"
b) and start the next stage by mapping forests as the array of
documents that are input to the "count all leaves"?
Note - I tried to get just (b) working for starters, but I can't seem to treat "forests" as an array so that the solution in the link above can do its magic.
Then- when that phase is done, extract what was stored in (a) to get the original format back with all the counts.

That is the main disadvantage of using $group. You have to explicitly carry forward every non participating fields using either $first or $last like this:
Get the test data with those additional fields from this new MongoPlayground link.
Check the updated query taken from the link:
db.Forests.aggregate([
{ $unwind: "$forests" },
{ $unwind: "$forests.trees" },
{ $unwind: "$forests.trees.branches" },
{
$lookup: {
from: "Leaves",
localField: "forests.trees.branches.branch_id",
foreignField: "branch_id",
as: "forests.trees.branches.leaves"
}
},
{
$addFields: {
"forests.trees.branches.leaf_count": { $size: "$forests.trees.branches.leaves" }
}
},
{
$project: { "forests.trees.branches.leaves": 0 }
},
{
$group: {
_id: {
forest_id: "$forests.forest_id",
tree_id: "$forests.trees.tree_id"
},
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$forests.trees.branches.leaf_count" },
branches: { $push: "$forests.trees.branches" }
}
},
{
$group: {
_id: "$_id.forest_id",
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$leaf_count" },
trees: {
$push: {
leaf_count: { $sum: "$leaf_count" },
tree_id: "$_id.tree_id",
branches: "$branches"
}
}
}
},
{
$group: {
_id: null,
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$leaf_count" },
forests: {
$push: {
leaf_count: { $sum: "$leaf_count" },
forest_id: "$_id",
trees: "$trees"
}
}
}
},
{
$project: { _id: 0 }
}
])
Output:
{
"forest_ranger" : "bob",
"some_other_data" : {
"data" : "Dummy data"
},
"leaf_count" : 4,
"forests" : [
{
"leaf_count" : 3,
"forest_id" : "forestA",
"trees" : [
{
"leaf_count" : 1,
"tree_id" : "treeB",
"branches" : [
{
"branch_id" : "branchB",
"leaf_count" : 1
}
]
},
{
"leaf_count" : 2,
"tree_id" : "treeA",
"branches" : [
{
"branch_id" : "branchA",
"leaf_count" : 1
},
{
"branch_id" : "branchA1",
"leaf_count" : 1
},
{
"branch_id" : "branchA2",
"leaf_count" : 0
}
]
}
]
},
{
"leaf_count" : 1,
"forest_id" : "forestB",
"trees" : [
{
"leaf_count" : 0,
"tree_id" : "treeD",
"branches" : [
{
"branch_id" : "branchD",
"leaf_count" : 0
}
]
},
{
"leaf_count" : 1,
"tree_id" : "treeC",
"branches" : [
{
"branch_id" : "branchC",
"leaf_count" : 1
}
]
}
]
},
{
"leaf_count" : 0,
"forest_id" : "forestC",
"trees" : [
{
"leaf_count" : 0,
"tree_id" : "treeE",
"branches" : [
{
"branch_id" : "branchE",
"leaf_count" : 0
}
]
}
]
}
]
}

Related

Hide nested fields with "name" in $project mongodb

This is the document available that needs to be projected by hiding all the "name" fields in the document. Not sure if we have any specific way in mongo aggregation framework to search for all the nested fields with name - "name" and hide it. Please suggest
"group1":{
"field1":{
"name":"a"
},
"field2":{
"data":{
"name":"b"
}
},
"group2":{
"field2":{
"name":"a"
},
"field3":{
"data":{
"name":"b"
}
}
}
}
}
Expected output:
{
group1: {
field1: {
}, "field2": {
"data": {
}
},
"group2": {
"field2": {
}, "field3": {
"data": {
}
}
}
}
}

mongodb aggregation query to include a specific field

I have a mongodb schema which looks like
{
post_id: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Post"
},
comment_by: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User"
},
comment: {
type: String,
required: true
},
parent_comment_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
},
is_deleted: {
type: Boolean,
default: false
}
}
I want to group the comments such that
they have common "parent_comment_id" but I also want to include the "comment" field of the
document whose "id" is "parent_comment_id".
This is query I have written
var comments = await Comment.aggregate([
{
"$match": {
post_id: mongoose.Types.ObjectId(post_id)
}
},
{
"$group": {
_id: `$parent_comment_id`,
replies: { "$count": {} }
}
}
])
and the result is
{ _id: new ObjectId("6278e11fa7887263e6e6fada"), replies: 3 },
{ _id: new ObjectId("6278fb9f6a8d30c46eb53a84"), replies: 5 },
{ _id: null, replies: 2 }
Result I want
{ _id: new ObjectId("6278e11fa7887263e6e6fada"), replies: 3 , comment : <comment>},
{ _id: new ObjectId("6278fb9f6a8d30c46eb53a84"), replies: 5 , comment : <comment>},
Welcome heeya joshi!.
You can do something like this:
db.collection.aggregate([
{
$match: {post_id: mongoose.Types.ObjectId(post_id)}
},
{
$addFields: {
parent_comment_id: {$ifNull: ["$parent_comment_id", "$_id"]}
}
},
{
$group: {
_id: "$parent_comment_id",
"comment": {
$push: {
$cond: [
{$eq: ["$parent_comment_id", "$_id"]},
"$comment",
"$$REMOVE"
]
}
},
replies: {"$count": {}}
}
},
{
$project: {
comment: {$arrayElemAt: ["$comment", 0]},
replies: 1
}
}
])
As you can see here.
After your $match, the addFields adds the parent_comment_id to the parents themselves. Then the $group keeps the comment only for the parents.

structure of xstate config which has condion included & which can be used in vue-kanban pkg

I'm trying to create xstate Machine which has condition to be check when moving to another state(Using VueJs).
issue is the way tried which is not working with vue-kanban(https://github.com/BrockReece/vue-kanban) pkg
below is my sample state machine config :
stateMachineConfig: {
id: "kanban",
initial: "on-hold",
states: {
"on-hold": {
on: {
IN_PROGRESS:"in-progress",
}
},
"in-progress": {
on: {
RELINQUISH_TASK: "on-hold",
PUSH_TO_QA: "needs-review",
},
},
"needs-review": {
on: {
REQUEST_CHANGE: "in-progress",
PASS_QA: "approved",
},
},
approved: {
type: "final",
},
},
},
this is the UI of kanban(https://ibb.co/6rWxN0F)
after i changing above config by adding condition to "on-hold" state then i can't move to anywhere from "on-hold" state.
below is the new config:
const searchValid = (context) => {
console.log(`context.status `, context);
return true;
};
stateMachineConfig: {
id: "kanban",
initial: "on-hold",
states: {
"on-hold": {
on: {
PICK_UP: [
{
target: "in-progress",
cond: searchValid
}
]
}
},
"in-progress": {
on: {
RELINQUISH_TASK: "on-hold",
PUSH_TO_QA: "needs-review",
},
},
"needs-review": {
on: {
REQUEST_CHANGE: "in-progress",
PASS_QA: "approved",
},
},
approved: {
type: "final",
},
},
},
any help to fix it!
I have tested your machine using the XState visualizer and all works properly, you can check it here

How to fetching data JSON using react-native-dropdown?

I want to fetching data from JSON using Dropdown lib,
but I can't display these JSON.
Here's the code I have tried:
this.state = {"diagnosis": {
"type": [
"Oncology",
"Hip And Knee"
],
"kode": [
"123",
"321",
"3232",
"1231"
],
"PrimaryCat": [
"contoh1",
"contoh2",
"contoh3"
],
"Location": [
"jakarta",
"bogor",
"depok",
"tangerang",
"bekasi"
],
"Encountrace": [
"kga",
"tau",
"isi",
"menunya"
],
"fracture": [
"ini",
"juga",
"kaga",
"tau",
"isinya"
],
"healing": [
"yang",
"pasti",
"penyembuhan"
]
}}
render() {
let data = [{
value: 'Banana',
}, {
value: 'Mango',
}, {
value: 'Pear',
}];
return (
<View>
<Dropdown
label="testing"
data={this.state.diagnosis.type}
/>
</View>
);
}
}
with above code, the dropdown just displaying two rows of type, but the name of oncology or hip and knee doesn't show,
here's the example screen:
Am I doing something wrong?
This will work if you change your json in following format,
this.state = {"diagnosis": {
"type": [
{
value: "Oncology",
}, {
value: "Hip And Knee"
}
],
rest of the formats will be as above.
If you do not want to change the format of your json then, you have to do minor changes in your react-native-material-dropdown code,
Please go to this path,
react-native-material-dropdown->src->components->dropdown->index.js
Please do some changes in index.js, change your valueExtractor function like this way,
valueExtractor: ( value = {}, index) => value,
Hope it helps to you.
try following.
{"diagnosis": {
"type": [
{
value: "Oncology"
},
{
value: "Hip And Knee
}
],
"kode": [
{
value: "123"
},
{
value: "321"
},
{
value: "3232"
},
{
value: "1231
}
],
"PrimaryCat": [
{
value: "contoh1"
},
{
value: "contoh2"
},
{
value: "contoh3
}
],
"Location": [
{
value: "jakarta"
},
{
value: "bogor"
},
{
value: "depok"
},
{
value: "tangerang"
},
{
value: "bekasi
}
],
"Encountrace": [
{
value: "kga"
},
{
value: "tau"
},
{
value: "isi"
},
{
value: "menunya
}
],
"fracture": [
{
value: "ini"
},
{
value: "juga"
},
{
value: "kaga"
},
{
value: "tau"
},
{
value: "isinya
}
],
"healing": [
{
value: "yang"
},
{
value: "pasti"
},
{
value: "penyembuhan
}
]
}

Curve Line Graphic and Jsonfile

I realized this curve line graph using d3 and nvd3:
d3.json('/Models/Scripts/test_data2.json', function(data) {
nv.addGraph(function() {
var chart = nv.models.lineWithFocusChart();
// chart.transitionDuration(500);
chart.xAxis
.tickFormat(d3.format(',f'));
chart.x2Axis
.tickFormat(d3.format(',f'));
chart.yAxis
.tickFormat(d3.format(',.2f'));
chart.y2Axis
.tickFormat(d3.format(',.2f'));
d3.select('#chart svg')
.datum(data)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
});
The question is, how should I write my json file to recognize different curves?
If I have the following json it doesn't work with two or more lines. I did several tries.
[{"CurveArray":[{
"Line1":[
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]},
"Line2":[
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]}
]}]
I tried to modify so:
It doesn't work again.
[
{
key: "Line1",
value: [
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]
},
{
key: "Line2",
value: [
{
"x":-50000,
"y":0.0
},
{
"x":-59000,
"y":0.4
},
{
"x":-48000,
"y":2
},
{
"x":-49100,
"y":0.9
},
{
"x":-49800,
"y":0.7
}
]
}
]