mongoose populate different database - mongoose-populate

I have two databases in my program. One for saving users and roles and one for the rest.
1) my model User has a reference to Roles. So I can populate roles by doing:
User.find({}).populate('local.roles').sort({ email: 1 }).exec(function (err, users) { ...
This works perfect and I can get a user and his roles.
2) When I try to do the same, but with models that have a connection to another database, I get the infamous error:
"MissingSchemaError: schema hasn't been registered for model ..."
This is the way I code my models when they use a different connection:
var mongoose = require('mongoose');
// to define another mongoose connection
var configScrwebDB = require('./../../config/scrwebDatabase.js');
var scrwebDBConnection = mongoose.createConnection(configScrwebDB.url);
var aseguradoSchema = mongoose.Schema({
nombre: { type: String },
abreviatura: { type: String },
rif: { type: String },
direccion: { type: String }
});
module.exports = scrwebDBConnection.model('Asegurado', aseguradoSchema);
3) this is what I do to 'populate' some field in my query (and the one that fails with above error):
var query = Riesgo.find({ cia: filtroObject.ciaSeleccionada });
query.populate('asegurado');
query.sort("codigo");
query.select("codigo fechaInicio estado moneda");
query.exec(function (err, riesgos) { ...
Of course this is in another 'js' file; and I do my 'require', etc., in order to import my models; etc.
As I said before, I can populate when models use 'default' mongoose connection.
Any ideas how I should correct this will be appreciated ... Am I missing some obvious thing here?
Thanks and bye ...

I had the same error. You could use:
var query = Riesgo.find({ cia: filtroObject.ciaSeleccionada });
query.populate('asegurado','fields to retrieve',User);// User need to be defined in the file as an variable that contents the User model defined.
query.sort("codigo");
query.select("codigo fechaInicio estado moneda");
Refer link

Related

How to define client side schema in `react-apollo` application?

I am using react-apollo in my react applicant and I can't figure out how to implement a client side schema.
I have below type definition:
export const alertTypeDefs = gql`
type Query {
alert: Alert
}
type Alert {
message: String!
type: String!
duration: Int!
}
`;
It defines a Query which returns an alert object.
Below is the code I want to use this query.
const cache = new InMemoryCache();
export const createClient = () => {
return new ApolloClient({
cache,
typeDefs: [alertTypeDefs]
});
};
First I initialised a ApolloClient instance with memory cache and alertTypeDefs defined above. Then below is the code to run the query:
const client = createClient();
const data = client.readQuery({query: gql`
{
alert #client
}
`});
console.log('data:', data);
But I got this error Missing selection set for object of type Alert returned for query field alert when run readQuery on the client instance. It seems that the Alert is not defined. But I already defined the Alert query in the typeDefs. It works fine if I change the query code to below which I have to specify what to be returned inside { message }. But it doesn't seem to use the schema. What I expect is that I don't need to specify the return fields if it returns all fields in the schema object. Do I mis-understand the schema?
const data = client.readQuery({query: gql`
{
alert #client {
message
}
}
`});
console.log('data:', data);
If I have to specify the return fields one by one, what the point to define the schema?
This is expected behavior with GraphQL. You always need to specify inside the query which fields you're expecting. So in order to receive all the data you add the fields to the query:
const data = client.readQuery({query: gql`
{
alert #client {
message
type
duration
}
}
`});
console.log('data:', data);
There is an open issue inside the GraphQL specs.
You can define a fragment with all the fields of the entity and then reuse it.
Like this
fragment AllAlertFields on Alert {
message
type
duration
}
And then in a query
query {
allAlerts {
...AllAlertFields
}
}
More details: https://www.apollographql.com/docs/react/data/fragments/

How do should I approach a local server in conjunction with graphQL schemas?

(Currently not using Apollo)
So I have server.js:
let graphqlHTTP = require('express-graphql');
... // (other graphQL setup)
let users = []; // or any DB solution here
const {
UserType,
UserFactory
} = require('./schema/typeDef.js');
const { QueryType } = require('./schema/query.js');
... // similar imports
// other server declarations
And for example, I have typeDef.js:
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: new GraphQLNonNull(GraphQLInt) },
username: { type: new GraphQLNonNull(GraphQLString }
}
});
const UserFactory = function(username, id) {
return {username: username, id: id};
};
module.exports = { UserType, UserFactory };
The problem is, I want to be able to add the UserType to the DB (in this code example, the users array) in server.js; but of course, typeDef.js does not have access to the declared DB in server.js.
I initially separated the files because I didn't want server.js to be too bloated with schema code.
How should I go about this? Thanks!
If you've come to the sacred land with no answer, I've got one for you. Follow the guide in this link.
Essentially, create a db with mongoose, export it, and use index.js in different folders to stitch them together. Resolvers will be in a different folder than types, each with their own index.js.
You can now access db methods in resolvers by having it require the db module. Note that you do not need babel, and I've found that cors causes problems (so you may want to remove that if it's causing you problem too).

Unable to call lifecycle methods in Strapi models?

I have a Strapi project with a MongoDB database and a simple Post model. This model has, among others, a slug field with the following attributes:
type: string,
unique: true,
required: true
For testing purposes, I am attempting to modify this field's value before committing it to the DB, via one of Strapi's lifecycle methods:
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
beforeSave: async (model) => {
// Set the password.
const newslug = model.slug + '-test';
model.slug = newslug;
},
};
But the method just doesn't seem to get fired as expected when I save a post on my admin page. The post, along with its slug, gets upserted to the DB without the modification shown in the code above. Am I misunderstanding the functionality?
If you are using NoSQL database (Mongo)
beforeSave: async (model) => {
if (model.content) {
model.wordCount = model.content.length;
}
},
beforeUpdate: async (model) => {
if (model.getUpdate().content) {
model.update({
wordCount: model.getUpdate().content.length
});
}
},
If you are using SQL (SQLite, Postgres, MySQL)
beforeSave: async (model, attrs, options) => {
if (attrs.content) {
attrs.wordCount = attrs.content.length;
}
},

Parse Cloud Code: Modify Object before Retrieval

Let's say I have a Users class and a Posts class, and each Post object has a User pointer. I also have a Comment class, and each Comment has a User pointer. Whenever I fetch a User, I want to fetch all the Posts and Comments that user has made in one network query. Compounding sub-queries won't work, since I have multiple data types. Ideally, I would like to have the Posts and Comments be properties of the retrieved User object.
Is there a way, in Cloud Code, to intercept object requests and modify them to have the appropriate properties before sending to the client?
You can't modify an object on retrieval, but you can write your own Cloud Function. In your Cloud Function you could take the ID of a user as a parameter, then create a composite object by combining the output of your 3 queries into one result.
You'll need to query:
User object
Posts for that user
Comments for that user
You could get the promise for each of those queries (find() etc return a promise object) and use Parse.Promise.when(userQueryPromise, postQueryPromise commentQueryPromise) to build your composite object and return it.
var _ = require('underscore');
Parse.Cloud.define('getUserWithPostsAndComments', function(request, response) {
var userId = request.params.userId;
var userPointer = new Parse.User();
userPointer.id = userId;
var userQuery = new Parse.Query(Parse.User);
var postQuery = new Parse.Query('Post');
postQuery.equalTo('user', userPointer);
var commentQuery = new Parse.Query('Comment');
commentQuery.equalTo('user', userPointer);
Parse.Promise.when(userQuery.get(userId), postQuery.find(), commentQuery.find())
.then(function(user, posts, comments) {
var composite = {
// User properties you want
name: user.get('username'),
email: user.get('email')
};
// Post properties you want
composite.posts = _.map(posts, function(post) {
return {
id: post.id,
title: post.get('title')
};
});
// Comment properties you want
composite.comments = _.map(comments, function(comment) {
return {
id: comment.id,
body: comment.get('bodyText')
};
});
// return the composite object
response.success(composite);
}, function(error) {
response.error(error);
});
});
Alternatively the above then block could just return the raw results, e.g.:
.then(function(user, posts, comments) {
return {
user: user,
posts: posts,
comments: comments
};
}, function(error) {
// etc...

Custom validation of mongoose's Schema params

have the next params of object:
var mongoose = require (PATH);
var Schema = mongoose.Schema;
var schema - new Schema ({
barcode:{
type:number,
required:true,
unique:true
},...});
i want to validate 'barcode', which will be no less and no more than 14 characters;
for this i write the code below:
schema.path('barcode').validate(function(barcode){
return barcode.length == 13;
}, 'sorry, the error occurred, be careful while typing, 14 characters only!");
exports.Item = mongoose.model('Item', schema);
But when i implement this schema to the concrete object, this validation does not play any role. I mean, that i can type any length of number and no any error occur!
Checkout mongoose-validator. It integrates with mongoose to support custom validation. You can use it something like this.
var validate = require('mongoose-validator').validate;
var BarcodeSchema = new Schema({
code: {
type: String,
required: true,
unique: true,
validate: validate('len', 13)
}
});

Resources