Meteor cross collection arrays - javascript

I am trying to pull an array from a different collection using collection2. I have been able to do this with objects using the following example for users:
users: {
type: String,
label: "Inspector",
optional: true,
autoform: {
firstOption: 'Choose an Inspector',
options: function() {
return Meteor.users.find({}, {
sort: {
profile: 1,
firstName: 1
}
}).map(function(c) {
return {
label: c.profile.firstName + " " + c.profile.lastName,
value: c._id
};
});
}
}
},
I would like to do the same but for an array of objects. Here is what the source data looks like:
{
"_id": "xDkso4FXHt63K7evG",
"AboveGroundSections": [{
"sectionName": "one"
}, {
"sectionName": "two"
}],
"AboveGroundItems": [{
"itemSection": "one",
"itemDescription": "dfgsdfg",
"itemCode": "dsfgsdg"
}, {
"itemSection": "two",
"itemDescription": "sdfgsdfg",
"itemCode": "sdfgsdgfsd"
}]
}
Here is what my function looks like:
agSection: {
type: String,
optional: true,
autoform: {
firstOption: 'Select A Section Type',
options: function() {
return TemplateData.find({}, {
sort: {
AboveGroundSections: 1,
sectionName: [0]
}
}).map(function(c) {
return {
label: c.AboveGroundSections.sectionName,
value: c.AboveGroundSections.sectionName
}
});
}
}
},
I know this, it's just not pulling the data for me. I am sure, I am just missing something small. I am trying to pull all objects within the AboveGroundSection array.

Your .map() is iterating over the set of documents but not over the arrays inside each document. Also I don't think your sorting is going to work the way you hope because of the inner nesting.
Try:
agSection: {
type: String,
optional: true,
autoform: {
firstOption: 'Select A Section Type',
options() {
let opt = [];
TemplateData.find().forEach(c => {
c.AboveGroundSections.forEach(s => { opt.push(s.sectionName) });
});
return opt.sort().map(o => { return { label: o, value: o } });
}
}
},
Also if your AboveGroundSections array only has a single key per element then you can simplify:
"AboveGroundSections": [
{ "sectionName": "one" },
{ "sectionName": "two" }
]
To:
"AboveGroundSections": [
"one",
"two"
]

Related

Comparison of two arrays regarding the text

I've got two arrays which i want to compare. Therfore i want to check if they got equal elements regarding the "text": .... If its equal it should return true, otherwise return false
englishData = [
{"data":"sandwich","text":"Sandwich"},
{"data":"toast","text":"Cuisine"},
{"data":"fries","text":"Pommes"},
{"data":"salad","text":"Salad"},
]
franceData = [
{"data":"sandwich","text":"Sandwich"},
{"data":"toast","text":"Kitchen"},
{"data":"fries","text":"Pommes"}]
So far i tried it with a normal for-loop, like :
for (let i = 0; i < actualData; i++) {
for (let j = 0; j < plannedData; j++) {
if (actualData[i].text === plannedData[i].text) {
return true
} if (actualData[i].text != plannedData[j].text) {
continue;
}
}
return false
}
}
Because of the different length, i wanted to compare each element in franceData with all elements in the original array englishData.
Its kinda woking, but im not sure if it's really the best solution regarding the performance, ... .
I also thought about some if statements, like:
if(franceData.text.includes(englishData.text)){ return true }
If you are looking to find out common elements, you can try something like this
englishData = [
{ data: "sandwich", text: "Sandwich" },
{ data: "toast", text: "Cuisine" },
{ data: "fries", text: "Pommes" },
{ data: "salad", text: "Salad" },
];
franceData = [
{ data: "sandwich", text: "Sandwich" },
{ data: "toast", text: "Kitchen" },
{ data: "fries", text: "Pommes" },
];
var res = englishData.filter((ede) =>
franceData.some((fde) => ede.text === fde.text)
);
console.log(res);
output:
[
{ data: 'sandwich', text: 'Sandwich' },
{ data: 'fries', text: 'Pommes' }
]
You can use map() in the place of filter to get just true or false for every match.
englishData = [
{ data: "sandwich", text: "Sandwich" },
{ data: "toast", text: "Cuisine" },
{ data: "fries", text: "Pommes" },
{ data: "salad", text: "Salad" },
];
franceData = [
{ data: "sandwich", text: "Sandwich" },
{ data: "toast", text: "Kitchen" },
{ data: "fries", text: "Pommes" },
];
var res = englishData.map((ede) =>
franceData.some((fde) => ede.text === fde.text)
);
console.log(res.join("\n"));
output:
true
false
true
false

Sequelize adding many-to-many relation with additional data not working

I have the following models defined:
var Order = sequalize.define(
"order",
{
id: {
type: Sequelize.STRING,
primaryKey: true,
},
menuId: {
type: Sequelize.UUID,
field: "menu_id",
},
},
{
timestamps: false,
}
);
Item.belongsToMany(Order, { through: OrderItem });
Order.belongsToMany(Item, { through: OrderItem });
and
var OrderItem = sequalize.define(
"order_item",
{
orderId: {
type: Sequelize.UUID,
field: "order_id",
},
itemId: {
type: Sequelize.UUID,
field: "item_id",
},
count: {
type: Sequelize.INTEGER,
field: "count",
},
},
{
timestamps: false,
freezeTableName: true,
}
);
I am trying to figure out how to add a order with items without creating items but just adding them to the relationship.
I have this initial format for the order:
{
"id": "som-other-id7",
"items": [{"id": "727f9b52-a88b-4ec3-a68c-98d190564497", "count": 2}, {"id": "7dfd30e7-2d4a-4b16-ae3d-20a330d9b438"}],
"menuId": "7715af03-968f-40e5-9eb2-98016f3deeca"
}
and I try to add it to the db in the following way:
Order.create(orderJson)
.then((order) =>
orderJson.items.map((item) => order.addItem(item.id, { count: item.count }))
)
However the count is not populated. I tried:
using setItem instead of addItem
instead of passing item.id passing {itemId, orderId}
You should call addItem like this:
order.addItem(item.id, { through: { count: item.count }})
See an example in BelongsToMany section

Ramda.js Combine two array of objects that share the same property ID

I have these two array of objects
todos: [
{
id: 1,
name: 'customerReport',
label: 'Report send to customer'
},
{
id: 2,
name: 'handover',
label: 'Handover (in CRM)'
},
]
And:
todosMoreDetails: [
{
id: 1,
checked: false,
link: {
type: 'url',
content: 'http://something.com'
},
notes: []
},
{
id: 2,
checked: false,
link: {
type: 'url',
content: 'http://something.com'
},
notes: []
}
]
So that the final array of objects will be a combination of the two, based on the object ID, like below:
FinalTodos: [
{
id: 1,
checked: false,
link: {
type: 'url',
content: 'http://something.com'
},
notes: [],
name: 'customerReport',
label: 'Report send to customer'
},
{
id: 2,
checked: false,
link: {
type: 'url',
content: 'http://something.com'
},
notes: [],
name: 'handover',
label: 'Handover (in CRM)'
}
]
I tried with merge mergeAll and mergeWithKey but I am probably missing something
You can achieve this with an intermediate groupBy:
Transform the todosMoreDetails array into an object keyed by todo property ID using groupBy:
var moreDetailsById = R.groupBy(R.prop('id'), todosMoreDetails);
moreDetailsById is an object where the key is id, and the value is an array of todos. If the id is unique, this will be a singleton array:
{
1: [{
id: 1,
checked: false,
link: {
type: 'url',
content: 'http://something.com'
},
notes: []
}]
}
Now transform the todos array by merging each todo to it's details you retrieve from the grouped view:
var finalTodos = R.map(todo => R.merge(todo, moreDetailsById[todo.id][0]), todos);
An alternate more detailed way:
function mergeTodo(todo) {
var details = moreDetailsById[todo.id][0]; // this is not null safe
var finalTodo = R.merge(todo, details);
return finalTodo;
}
var moreDetailsById = R.groupBy(R.prop('id'), todosMoreDetails);
var finalTodos = todos.map(mergeTodo);
I guess merge is only used for arrays. Have a search for object "extend". Maybe storing the todo details not in seperate objects is the better solution.
Using jQuery? https://api.jquery.com/jquery.extend/
Using underscore? http://underscorejs.org/#extend
Native approach? https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
Using underscore:
var result = [];
var entry = {};
_.each(todos, function(todo) {
_.each(todosMoreDetails, function(detail) {
if (todo.id == detail.id) {
entry = _.extend(todo, detail);
result.push(entry);
}
}
});
return result;

How to merge two object with different properties

I have something like this :
let user = [
{
name: "step-one",
values: {companyName: "Name", address: "company address"}
},
{
name: "step-two",
values: {name: "User", mobile: 0123}
},
{
name: "step-three",
values: [
{file: "companyLogo", values: {active: true, fileName: "some name"}},
{file: "avatar", values: {active: true, fileName: "file name"}}
]
}
]
I want to get only values and put them into a new object. Thus, something like :
let wantedResult = {
companyName: "Name",
address: "company address",
name: "User",
mobile: 0123,
files: [
{file: "companyLogo", values: {active: false, fileName: "some name"}},
{file: "avatar", values: {active: false, fileName: "file name"}}
]
};
Any advice how I can do that?
You can try this!
let user = [{
name: "step-one",
values: {
companyName: "Name",
address: "company address"
}
}, {
name: "step-two",
values: {
name: "User",
mobile: 0123
}
}, {
name: "step-three",
values: [{
file: "companyLogo",
values: {
active: true,
fileName: "some name"
}
}, {
file: "avatar",
values: {
active: true,
fileName: "file name"
}
}]
}]
var wantedResult = Object.assign({}, user[0].values, user[1].values, {files: user[2].values})
console.log(wantedResult)
It is a bit hacky because of the files array, but i would do it like that:
var wantedResult = user.reduce((result, step) => {
var values = Array.isArray(step.values) ? { files: step.values } : step.values;
return Object.assign({}, result, values)
}, {});
Of course it'll work only for that kind of structure you provided. If you have more objects that have an array in the 'values' property, you'll need to rethink the approach.
Step 3 is inconsistent with the others. If possible, make it consistent to have: values: files: [ { file1_data }, { file2_data } ].
After fixing the inconsistency, you can iterate through each of the steps and add the new properties to the result.
let wantedResult = user.reduce(function(result, spec) {
Object.keys(spec.values).forEach(function(key) {
result[key] = spec.values[key];
});
return result;
}, {});
If not possible to change step 3, you can make it a bit less clean:
let wantedResult = user.reduce(function(result, spec) {
if (spec.name === "step-three") {
result.files = spec.values;
}
else {
Object.keys(spec.values).forEach(function(key) {
result[key] = spec.values[key];
});
}
return result;
}, {});

Querying nested objects in PouchDB

I googled some examples and tutorials but couldn't find any clear example for my case.
I get a JSON response from my server like this:
var heroes = [
{
id: 5,
name: 'Batman',
realName: 'Bruce Wayne',
equipments: [
{
type: 'boomarang',
name: 'Batarang',
},
{
type: 'cloak',
name: 'Bat Cloak',
},
{
type: 'bolas',
name: 'Bat-Bolas',
}
]
},
{
id: 6,
name: 'Cat Woman',
realName: 'Selina Kyle',
equipments: [
{
type: 'car',
name: 'Cat-illac',
},
{
type: 'bolas',
name: 'Cat-Bolas',
}
]
}
];
I would like to query for example: "get heroes with equipment type of bolas"
and It should return both hero objects in an array.
I know it is not right but what I am trying to do is to form a map function like this:
function myMapFunction(doc) {
if(doc.equipments.length > 0) {
emit(doc.equipment.type);
}
}
db.query(myMapFunction, {
key: 'bolas',
include_docs: true
}).then(function(result) {
console.log(result);
}).catch(function(err) {
// handle errors
});
Is it possible? If not what alternatives do I have?
P.S: I also checked LokiJS and underscoreDB. However PouchDB looks more sophisticated and capable of such query.
Thank you guys in advance
Your map function should be:
function myMapFunction(doc) {
doc.equipments.forEach(function (equipment) {
emit(equipment.type);
});
}
Then to query, you use {key: 'bolas'}:
db.query(myMapFunction, {
key: 'bolas',
include_docs: true
}).then(function (result) {
// got result
});
Then your result will look like:
{
"total_rows": 5,
"offset": 0,
"rows": [
{
"doc": ...,
"key": "bolas",
"id": ...,
"value": null
},
{
"doc": ...,
"key": "bolas",
"id": ...,
"value": null
}
]
}
Also be sure to create an index first! Details are in the PouchDB map/reduce guide :)

Categories