Meteor: Composite publish to get data from two collections - javascript

I try to use reywood:publish-composite. But something I'm doing wrong as I want to load the article-data and the assigned literature-data.
I think my main problem is to set the route correctly to get the data into the variables, which I could use in the template.
Persume I would open /article/BpsCfbhZuoXfEvREG:
publications.js
Meteor.publishComposite('articles', function(){
return {
find: function(){
return Articles.find();
},
children: [{
find: function(article){
return Literature.find({'article.detail.reference': article._id})
}
}]
}
});
router.js
Router.route('/article/:_id', {
name: 'article',
waitOn: function() {
return Meteor.subscribe('articles'); /* correct? */
},
data: function () {
return {
article: Articles.findOne({
_id: this.params._id
}),
references: Literature.find({}) /* guess, this is wrong */
};
}
});
Literature has this structure and I'm looking for reference:
{
"_id" : "YAEYvJ7tvXxTvnFtv",
"article" : [
{
"title" : "Article 1",
"detail" : [
{
"reference" : "BpsCfbhZuoXfEvREG",
"year" : 2000,
}
]
}
]
}

You want to load an individual article? That looks like what you are doing but you are subscribing to all articles. You could pass the parameter to your subscription.
waitOn: function () {
return Meteor.subscribe('article', this.params._id);
}
Secondly, since your Literature is an array of objects, you should use $elemMatch
Meteor.publishComposite('article', function (articleId) {
check(articleId, String);
return {
find: function () {
return Articles.find(articleId);
},
children: [{
find: function (article) {
return Literature.find({
'article.detail': {
$elemMatch: {
'reference': article._id
}
}
});
}
}]
}
});

Related

Update mongo collection with values from a javascript map

I have a collection that looks like this
[
{
"project":"example1",
"stores":[
{
"id":"10"
"name":"aa",
"members":2
}
]
},
{
"project":"example2",
"stores":[
{
"id":"14"
"name":"bb",
"members":13
},
{
"id":"15"
"name":"cc",
"members":9
}
]
}
]
I would like to update the field members of the stores array taking getting the new values from a Map like for example this one
0:{"10" => 201}
1:{"15" => 179}
The expected result is:
[
{
"_id":"61",
"stores":[
{
"id":"10"
"name":"aa",
"members":201
}
]
},
{
"_id":"62",
"stores":[
{
"id":"14"
"name":"bb",
"members":13
},
{
"id":"15"
"name":"cc",
"members":179
}
]
}
]
What are the options to achieve this using javascript/typescript?
In the end, I resolved by updating the original database entity object with the values in the map, then I have generated a bulk query.
for (let p of projects) {
for(let s of p.stores) {
if(storeUserCount.has(s.id)){
s.members = storeUserCount.get(s.id);
}
};
bulkQueryList.push({
updateOne: {
"filter": { "_id": p._id },
"update": { "$set": {"stores": p.stores} }
}});
};
await myMongooseProjectEntity.bulkWrite(bulkQueryList);
You can use update() function of Mongoes model to update your expected document.
Try following one:
const keyValArray= [{"10": 201},{"15":"179"}];
db.collectionName.update({_id: givenId},
{ $push: { "stores": {$each: keyValArray} }},
function(err, result) {
if(err) {
// return error
}
//return success
}
});

deep filtering on array of objects

I have data like this one below
let data = [
{
name: 'basic',
to: 'aaa',
subMenus: [
{
name: 'general conc',
to: 'geneal',
},
{
name: 'example view',
to: 'example',
},
{
name: 'fancy',
to: 'bbb',
innerSubMenus: [
{
name: 'adding',
to: 'add',
},
{
name: 'getting',
to: 'get',
},
]
}
]
}
]
I need to filter data based on name (in main, subMenus, and innerSubMenus)
Here is the piece of code
function deepFilter(inputText){
data.filter(items => items.name.toLowerCase().includes(inputText.toLowerCase()))
}
As you can see, the function filters the first prop (name --> basic in this case when inputText = 'basic', doesn't work when inputText = 'general conc') but I want to be able to filter names in subMenus and innerSubMenus as well. Please, guide me on how to do it. Thanks
expected outputs:
deepFilter('basic') -> true // only this part is covered by my implementation
deepFilter('general conc') -> true
deepFilter('adding') -> true
deepFilter('ffff') -> false //since there is not name with value of 'ffff' in data
I think this should work well.
function deepFilter(inputText, datas) {
return datas.filter(data => {
function checkInsideObj(object, inputText) {
for (let value of Object.values(object)) {
if (object.name && object.name.toLowerCase() === inputText.toLowerCase()) {
return true;
}
if (Array.isArray(value)) {
return value.some(item => {
return checkInsideObj(item, inputText)
}
)
}
}
return false;
}
return checkInsideObj(data, inputText)
}
)
}
deepFilter("input", data)

vue this.array.find in methods/computed properties gives undefined

I have an array (approvalOptions) that i receive from getters in a component, from which i need to find a certain value.
Things i have tried:
Use it in methods (read from ...mapGetters) like so
methods: {
approvalDisplayName(value) {
console.log(this.approvalOptions)
return this.approvalOptions.find(it => it.key === value).displayName;
},
},
use it in computed (read from ...mapGetters) (code sample same as above, only difference being the use of computed properties' block instead of methods'
use it in methods (read from data properties) like so
data() {
return {
approvalOptions: [...(objects with keys and values here)]
}
},
methods: {
approvalDisplayName(value) {
console.log(this.approvalOptions)
return this.approvalOptions.find(it => it.key === value).displayName;
},
},
All three times I get an error in the console that approvalOptions.find(...) doesnt exist. The console.log also prints an array in the console so i really don't understand what is going on here.
Maybe this can help you
computed: {
approvalOptions() {
return [
{ key: 1, displayName: "Name 1" },
{ key: 2, displayName: "Name 2" }
];
}
},
methods: {
approvalDisplayName(options, value) {
return options.find((it) => it.key === value).displayName;
}
},
created() {
console.log(this.approvalDisplayName(this.approvalOptions, 1));
}

Array of functions - Javascript

I'm developing a vue-based system, and for my tables, I'm using this: https://github.com/matfish2/vue-tables-2
The component has lots of options. There's the possibility to define custom cell templates to manipulate data before showing them, like this one for the "created_at" column:
templates: {
created_at(h, row) {
return this.formatDate(row.created_at);
},
//(...)
}
I can add other templates as well:
var user_id = function(h,row){return row.id};
...
templates: {
created_at(h, row) {
return this.formatDate(row.created_at);
},
user_id,
(...) // etc
}
But I'd like to group the functions into a variable, so I could reuse the code, like:
var custom_template = [
{ user_id(h,row){return row.id} },
{ user_name(h,row){return row.name} },
{ created_at(h, row){return this.formatDate(row.created_at)} }
];
templates: {
custom_templates
}
EDIT 1:
So i could have something like:
templates: {
user_id(h,row){return row.id} ,
user_name(h,row){return row.name} ,
created_at(h, row){return this.formatDate(row.created_at)}
}
It's not working, but is it possible? Do I need extra code to achieve this?
Thanks! =)
var custom_template = [
function user_id(h, row) {
return row.id;
},
function user_name(h, row) {
return row.name;
},
function created_at(h, row) {
return row.created_at;
}
];
custom_template.forEach(
item => console.log(item(1, {
id: 1,
name: "test",
created_at: new Date()
})));
You need to combine Igor's solution to create array of functions with some form of expanding the array, such as the spread syntax

Related items in Meteor

I have groups and items and the items are related to specific groups. At the "detail page" of a group I want to see all the items belonging to the specific group.
I've tried this
Router.route('/group/:_id', {
name: 'group',
template: 'group',
waitOn: function () {
return this.subscribe("groups", this.params._id);
},
data: function () {
return {
group: Groups.findOne(this.params._id);
items: Items.find({groupId: this.params._id}),
}
}
});
But what should waitOn look like if it should both wait for the specific group AND the items belonging to the group?
You can return an array of subscriptions to wait on:
waitOn: function () {
return [
Meteor.subscribe("groups", this.params._id),
Meteor.subscribe("items", this.params._id)
]
}
You can either have another publish function
Meteor.publish('relatedItems', function (groupId) {
return Items.find({groupId: groupId});
});
and wait for the two subscriptions
waitOn: function () {
return [
Meteor.subscribe("groups", this.params._id),
Meteor.subscribe("relatedItems", this.params._id)
];
},
or you can add to your existing publication like this:
Meteor.publish('groups', function (groupId) {
return [
Groups.find({_id: groupId}),
Items.find({groupId: groupId}),
];
});

Categories

Resources