My app has a "Categories" model.
Categories can be children of other categories.
So there is a "CategoriesAssociations" model.
Here is the code :
/* api/models/Categories.js */
module.exports = {
attributes: {
name: {
type: "string"
},
parents: {
collection: "categoriesassociations",
via: "child"
},
children: {
collection: "categoriesassociations",
via: "parent"
}
}
}
/* api/models/CategoriesAssociations.js */
module.exports = {
attributes: {
parent: {
model: "categories"
},
child: {
model: "categories"
}
}
}
Now when I use the find route aka /categories I get this :
[
{
"createdAt": "2015-08-24T14:16:46.662Z",
"updatedAt": "2015-08-24T14:24:23.819Z",
"name": null,
"id": "55db274e424996cc7e7512e2"
},
{
"createdAt": "2015-08-24T14:18:29.748Z",
"updatedAt": "2015-08-24T14:18:41.105Z",
"name": "test",
"id": "55db27b5424996cc7e7512e4"
}
]
So no trace of the parents and children properties.
The associations are indeed created in the database for when I request /categories/55db27b5424996cc7e7512e4/children I get this :
[
{
"parent": "55db27b5424996cc7e7512e4",
"child": "55db274e424996cc7e7512e2",
"createdAt": "2015-08-24T14:32:43.429Z",
"updatedAt": "2015-08-24T14:32:43.429Z",
"id": "55db2b0bc97cc73083017f60"
}
]
Sails docs states that the populate configuration key for blueprints defines :
Whether the blueprint controllers should populate model fetches with data from other models which are linked by associations. If you have a lot of data in one-to-many associations, leaving this on may result in very heavy api calls.
The value is true in my project but still, associations attributes don't get populated.
Did I misunderstand the docs or is there a problem with my project?
I use sails 0.11.x
The problem is I'm using sails-permissions which has overrides blueprints' populate config :
sails.config.blueprints.populate = false;
I opened an issue to know why it's done globally and how to fix the problem.
Related
I want to update or delete a particular field (subTags:) in an array of objects.
{
"_id": {
"$oid": "63c175a0ec5dac10b35ac9da"
},
"name": "clerk",
"description": "clerical duties including typing and filing.",
"tags": "assistant receptionist typist ",
"__v": 0,
"subCategory": [
{
"name": "tele-clerk",
"subTags": [
"assistant",
"receptionist"
]
},
{
"name": "administrative-clerk",
"subTags": [
"assistant",
"receptionist",
"typist"
]
}
]
}
I tried using :
const updatedSubCategory = await this.categories.findOneAndUpdate({name:category.name,"subCategory.name": category.subCategory.name},{ $addToSet:{subCategory: category.subCategory}},{new:true})
but it is creating another new object inside subcategory array of same name I don't want that to happen.The name field in the subcategory must be unique.
my schema is :
#Schema({collection:'category'})
export class SubCategorySchema {
#Prop({unique:true})
name:string
#Prop()
tags:string[]
}
#Schema({collection:'category'})
export class CategorySchema {
#Prop({unique:true, lowercase:true})
name:string
#Prop({lowercase:true})
subCategory:SubCategorySchema[]
#Prop({lowercase:true})
description:string
#Prop({lowercase:true})
tags:string
}
I have to store some users and their group relations like below
So I am planning to create a collection like below
UserGroupRelation Collections
{
"user":String,
"Group":String"
}
example of collections for Super admin users
{
"user":"Adminuser-1",
"Group":"Group1"
}
{
"user":"Adminuser-1",
"Group":"Group2"
}
{
"user":"Adminuser-1",
"Group":"Group3"
}
where user & Group column is indexed and I will run below kind of query
1.Whenever I want to check whether given user has access to the given group
db.UserGroupRelation.find( { user: "Adminuser-1", Group: "Group2" })
2.Also I want to delete all the association whenever we delete group
db.UserGroupRelation.deleteMany({ Group: "Group2" })
3.Also find all the users of a group
db.UserGroupRelation.find( { Group: "Group2" })
4.Find Hierarchy?, with my Approach I am not able to find
But with this approach I am duplicating lot of data also in real time I may have 10000 groups and 1 million user so there would be performance issue. And with this I am not able to maintain a hierarchy like SuperAdmin->SubAdmin->user of same group
I checked with mongo tree but it is not fitting to this requirement. is there a better way to handle this requirement in mongodb .?
This is the structure your graphic requirements show. It does still lead to repetition though so you will need to change it. Read up on one-many relationships.
{
"superAdmin_ID": "001",
"groups": [
{
"_id": "0",
"groupNumber": "1",
"users": [
{
"_userKey": "1023"
"userName": "Fred"
},
{
"_userKey": "1024"
"userName": "Steve"
}
],
"subAdmin": {
"_adminKey": "55230"
"adminName": "Maverick"
},
},
{
"_id": "1",
"groupNumber": "2",
"users": [
{
"_userKey": "1023"
"userName": "Fred"
},
{
"_userKey": "4026"
"userName": "Ella"
}
],
"subAdmin": {
"_adminKey": "55230"
"adminName": "Maverick"
},
},
{
"_id": "2",
"groupNumber": "3",
"users": [
{
"_userKey": "7026"
"userName": "James"
}
],
"subAdmin": {
"_adminKey": "77780"
"adminName": "Chloe"
},
},
]
}
You can also make subAdmin an array if you need more than one subAdmin within a group.
Can / how do you define an embedded document in a model's json definition with LoopbackJS without creating a model to represent the sub-document?
For example, consider this following MongoDB document:
{
_id: ObjectId("some_mongodb_id"),
subDocs: [
{
"propertyA": "a1",
"propertyB": "b1"
},
{
"propertyA": "a2",
"propertyB": "b2"
}
]
}
I could create two models in loopback:
some-model.json:
...
"properties": {
"subDocs": [
"SubDocsModel"
]
}
sub-docs-model.json:
...
"properties": {
"propertyA": "string",
"propertyB": "string"
}
Rather than doing that, however, I'd like to just declare the sub-doc model inline in the some-model.json since it's just there to document the shape of some-model's document.
Is that possible? Something like:
some-model.json:
...
"properties":{
"subDocs": [
{
"propertyA": {
"type": "string"
},
"propertyB": {
"type": "string"
}
}
]
}
I tried the above, but what I end up with is a field in my mongodb document that's of type string with the value [object Object]...
The purpose would be (1) to document the shape of the sub-document, and (2) to allow for validation by loopback without adding custom logic.
You can define it as an object
some-model.json:
"properties": {
"subDocs": ["object"]
}
But if you want validation or have a structure for sub-docs, you need to create a loopback model for that.
Loopback does not do any validation, ... for properties with type object.
In my application I have a list of tiles representing each project in a portfolio. This is the main list view for the app and all projects are fetched from the collection without any sorting or ordering.
When I have an optional slug parameter specified in my route (for the category assigned to the project) I want to be able to display the projects within the UI that match that category first, and then display the other ones that don't match the category.
For reference, I have included the code for the route below:
/**
* Project list view (all projects) with optional
* filter parameter for showing projects only by
* their category name.
*/
this.route('list', {
path: '/:_category_slug?',
template: 'template_main',
action: function() {
if(this.ready()) {
this.render();
}
},
waitOn: function() {
return [
Meteor.subscribe('projects'),
Meteor.subscribe('formations'),
Meteor.subscribe('categories')
];
},
data: function() {
if(this.params._category_slug) {
/**
* Building up the query given the category slug and the language
*/
var query = {};
query['slug.' + App.language] = this.params._category_slug;
/**
* Grab the category given the query, so we can get its 'id'
*/
var category = App.models.categories.findOne(query);
/**
* This is the query I need to work on so that I can achieve what I want
*/
return App.models.projects.find({}).fetch();
}
else {
return App.models.projects.find({}).fetch();
}
},
yieldTemplates: {
'components_header': {to: 'header'},
'views_list': {to: 'content'},
'components_footer': {to: 'footer'}
}
});
For reference, I have also included a sample of the data for three projects that is relevant to this question.
{
"id": 10,
"slug": {
"en": "sample-english-slug",
},
"title": {
"en": "Sample English Title",
},
"description": {
"en": "A good description.",
},
"category_ids": [
{
"id": 5
},
{
"id": 6
}
],
},
{
"id": 12,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "Another sample title",
},
"description": {
"en": "Sample description three",
},
"category_ids": [
{
"id": 1
},
{
"id": 4
}
],
},
{
"id": 11,
"slug": {
"en": "another-sample-slug",
},
"title": {
"en": "A sample title",
},
"description": {
"en": "Sample description",
},
"category_ids": [
{
"id": 2
},
{
"id": 5
}
],
}
So what I would want to do is make sure that given a category with an ID of 5, I want those first two projects to be the first two that appear.
Can this be done in meteor, without having to resort to writing extra logic in JS? One approach I did have once was to update each project from within the Client side collection (something I no longer do) and set a few extra attributes, then sort after that.
When dealing with syncing client and server collections, this is not really feasible.
From the mongodb docs:
Use the dot notation to match by specific fields in an embedded document. Equality matches for specific fields in an embedded document will select documents in the collection where the embedded document contains the specified fields with the specified values. The embedded document can contain additional fields.
I don't know if you can do it with a single query, but you can concat two complementary queries that use dot notation.
var selected = App.models.projects.find({'category_ids.id': category._id}).fetch();
var other = App.models.projects.find({'category_ids.id': {$ne: category._id}}).fetch();
return selected.concat(other);
Here below is a hypothetical Users collection where more than one address is allowed:
{
"firstName": "Joe",
"lastName": "Grey",
...
"addresses":
[
{
"name": "Default",
"street": "..."
...
},
{
"name": "Home",
"street": "..."
...
},
{
"name": "Office",
"street": "..."
...
}
]
}
Every address has a name... which should be unique – e.g. there couldn't be two addresses named Default. If I want to update let's say the address at index 1 (Home), how do I ensure the update data does not contain names Default and Office?
I guess a two-steps approach (i.e. find and then update) wouldn't be very correct since data might be updated between the find and the subsequent update operation, isn't?
var renamed = 'Office'; // from user input
var users = getUserMongoCollection();
users.update({_id:userId, 'addresses.name': { $ne : renamed } },
{ $set : { 'addresses.1.name' : renamed } }, function(err){
//all done!
});
Find the record by ID, and only update it if the array doesn't contain the new name.