moleculerjs / moleculer-db Goto Github PK
View Code? Open in Web Editor NEW:battery: Database access service mixins for Moleculer
Home Page: https://moleculer.services/
License: MIT License
:battery: Database access service mixins for Moleculer
Home Page: https://moleculer.services/
License: MIT License
In many cases it's desireable to have idemponent opreations that can be done against the database. Supporting upsert and upsertMany would blur the distinction between an insert and an update. To do this we also can't rely on the presence of an "ID" field to determine if a record already exists in the database or not. An alternate key is needed.
Hi
On line x498 in your moleculer-db/src/index.js file you do not return from the promise in case the if statement fails. Could you please add the following:
if (this.schema[eventName] != null) {
return this.schema[eventName].call(this, json, ctx);
}
return; // <--- this
so that we do not get the warnings?
Thanks and best,
Michael
Allow support of multi tenants
In settings
{
// this could be specific to the adapters
tenantStrategy: {
// if these keys are not preset we throw validation error
// and based on tenant strategy we might have to add these to every query we make to db
tenantKeys: ['accountId'], // or (config, params) => ['accountId']
// for mongo adapter return new db
getDB: (config, params) => config.client.db(`${config.collection}-${params.accountId}`),
// for mongo adapter return new collection
getCollection: (config, params) => config.db.collection(`${config.collection}-${params.accountId}`),
// for mongoose
getModel: (config, params) => config.model,
// if exists will override the adapter find or update the params and call adapter's find
find: () => null
// ... other methods
}
}
And tenant strategies can be implemented by the adapters itself, example incase of mongoose, whether to use that as shardKey
or use a separate collection
or use a separate db
It'd be really nice if I could create Mongo/Mongoose Adapters using a connection object instead of a connection string.
I want to create some mocha tests and today I have to keep a database running (in memory or full) to be able to connect to it.
By being able to initialise mongoose adapter using a connection, I could use mongoose-mock or some other mock api.
Is there a plan to add (sort/query) support for populating?
I'm running a very simple service, and I just can't get it to work, it just stops after 'Connected successfully...', no errors, it just stops, and I can't for the life of me figure out what is going on. Here's my test repo any help would be much appreciated.
$ node -v
v9.11.1
$ npm -v
5.8.0
var data = this.actions.list({
query: {
role: ctx.params.role,
},
fields: ["id", "username", 'firstName', 'lastName', 'birthday', 'idNumber', 'city' , 'district', 'ward', 'address', 'email', 'managerId', 'companyId', 'typeUser', 'allowModule'],
page: Number(ctx.params.page),
pageSize: SETTING.Paginate.LIMIT_RECORD,
search: 'Customer',
searchFields: ["username"]
})
I want to set search attribute and I have this error. I don't know how to fix?
Error: Invalid value { username: { '$like': '%Customer%' } }
When I call updateById method on mongo adpater , I get this error
Request error! MongoError : The _id field cannot be changed from {_id: ObjectId('5aa1785f6fabc20dccdaaabf')} to {_id: "5aa1785f6fabc20dccdaaabf"}.
Actually we need to passe _is without converting it to objectID
I did that in my code and the error disapeared but no update is done:
this.adapter.collection.findOneAndUpdate({ _id: (currentFolder._id/*string*/) }, currentFolder, { returnOriginal : false })
i was looking a way to get a global broker to use it in Model pre/post hooks, after i ran the project with the moleculer-runner which is the recommended way to do it so. I have not found how to get to the broker, since when i create a new one it cant see the other nodes even with the same namespace and transport.
is there a way?.
Hello,
can I populate without explicit set populate in find, list and get actions?
Populate fields already in settings, i want to populate this fields by default.
Hello,
I'm trying to run this code sniped:
user.service.js
module.exports = {
name: "user",
mixins: [DbService],
settings: {
fields: ["name", "email", "_id"]
},
afterConnected() {
this.broker.call("user.find").then((resp)=>{
if (resp.length!=0) return;
this.logger.info("Seed User Collection...");
return this.adapter.insertMany(
[
{ name: "John", email: "[email protected]", _id: '1' },
{ name: "Adam", email: "[email protected]", _id: '2' },
{ name: "Jane", email: "[email protected]", _id: '3' },
{ name: "Susan", email: "[email protected]", _id: '4' },
{ name: "Bill", email: "[email protected]", _id: '5' }
])
})
}
}
permission.service.js
module.exports = {
name: "permission",
mixins: [DbService],
settings: {
fields: ["name", "level", "_id"]
},
afterConnected() {
this.broker.call("permission.find").then((resp)=>{
if (resp.length!=0) return;
this.logger.info("Seed Permission Collection...");
return this.adapter.insertMany(
[
{ name: 'Level 02', level: '2', _id: '1' },
{ name: 'Level 01', level: '1', _id: '2' },
{ name: 'Level 03', level: '3', _id: '3' }
])
})
}
}
user_x_permission.service.js
module.exports = {
name: "user_x_permission",
mixins: [DbService],
settings: {
fields: ["user_id", "permission_id"]
},
populates: {
"user_id": {
action: "user.get",
params: {
fields: ["name", "email"]
}
},
"permission_id": {
action: "permission.get",
params: {
fields: ["name", "level"]
}
}
},
afterConnected() {
this.broker.call("user_x_permission.find").then((resp)=>{
if (resp.length!=0) return;
this.logger.info("Seed UserPermission Collection...");
return this.adapter.insertMany(
[
{ user_id: "2", permission_id: "1" },
{ user_id: "1", permission_id: "2" },
{ user_id: "3", permission_id: "3" }
])
});
}
}
And then:
broker.call("user_x_permission.find",{populate:["user_id"]}).then((resp)=>{ console.log(resp); }
And my response is:
[ { user_id: '3', permission_id: '3' }, { user_id: '1', permission_id: '2' }, { user_id: '2', permission_id: '1' } ]
Should not 'user_id' be populated? What I'm missing? I ran your sample and the result is correct, but on my service didn't get the populate to work.
I find moleculer-db is very confusing and frustrating, I am not sure but i can't make the database work as it's documented, i have to search for a domain in database but i am not getting the results i need:
this.broker.call('$database.service.get',{host : domain.params}).then(resolve) -> Unhandled rejection ValidationError: Parameters validation error!
tried this:
this.adapter.find({ host : domain.params }).then(resolve)
- > return all list of hosts in array that looks like this:
[{host:'host1.com'},{host:''hotst2.com}] but i need to find one host not all of them.
tried this:
this.find({ query: { host: domain.params } }).then(resolve)
UnhandledPromiseRejectionWarning: TypeError: this.find is not a function
here is my service:
module.exports = {
name : "$database.service",
adapter : new db.MemoryAdapter({ filename : 'hosts.db' }),
actions: {
init (domain) {
return new Promise((resolve) => {
this.adapter.insert(domain.params);
resolve();
});
},
getDomain(domain){
return new Promise((resolve) => {
this.adapter.find({ host : domain.params }).then(resolve);
//`this.broker.call('$database.service.get',{host : domain.params}).then(resolve) -> Unhandled rejection ValidationError: Parameters validation error!`;
//this.find({ query: { host: domain.params } }).then(resolve) UnhandledPromiseRejectionWarning: TypeError: this.find is not a function
});
}
}
}
Thank you
At present moleculer-db allows only for a single data model per service. There might be use cases where a service needs to manage multiple data entities (tables in a data schema).
Example:
Service: Access Control Service - a service managing role based access control for the stack.
Data Entities:
Currently, I would have to create a service for each data entity, i.e. role-service
, roleGroup-service
, function-service
, roleRunction-service
.
Each of these services will then link to the underlying data table, using the model
property of the service, e.g.:
model: {
name: "roles",
define: {
_id: Sequelize.INTEGER,
title: Sequelize.STRING,
status: Sequelize.STRING
}
}
Accessing the model methods:
this.model.findById(ctx.params.id)
It would be great if the model
property could accept an array of model objects. Accessing these from the service, would look something like:
this.model.roles.findById(ctx.params.id)
In src/index.js, the populateDocs(ctx, docs, populateFields)
function validates the docs parameter using:
if (docs == null || !_.isObject(docs) || !Array.isArray(docs))
This makes it so that docs must be an Array, not accepting docs as an Object.
I believe the correct validation should be something like:
if (docs == null || !_.isObject(docs) && !Array.isArray(docs))
I am just wondering how moleculer-sequelize adapter implements the relations for Sequelize?
As I understand the moleculer-db module, it only takes care of the CRUD operations to the DB, and everything else is taken care of in the service level (relationships). Is this true? if not, is there a way that this is handled by the adapter?
When I am populating it through the query params I have to add an additional blank attribute to make it an array
http://[ip]:[port]/users?populate=client&populate=
Otherwise, it will throw a validation exception.
I would like to use entityUpdated
hook to define some side logic, such as 'auto set statusUpdatedAt status if status is changed', but the problem is, there is no right way to get the previous doc and diff out if status was changed.
By now I used a workaround looking for ctx.params
, but that is not safe since there may be other update actions in the future which have different params definitions.
I'm using a custom Joi validator that not just validate the instance but also fix the object with defaults, conversions and etc.
I'm trying to create the entityValidator using a function, like...
entityValidator: function(entity) {
// do whatever
return entity;
},
However it's not respecting the custom function because a function is a subtype of object, following the snippet.
if (this.broker.validator && _.isObject(this.settings.entityValidator)) {
const check = this.broker.validator.compile(this.settings.entityValidator);
this.settings.entityValidator = entity => {
const res = check(entity);
if (res === true)
return Promise.resolve();
else
return Promise.reject(new ValidationError("Entity validation error!", null, res));
};
}
Then, it creates a function wrapping my custom function, which of course is wrong.
EDITED
I believe it's necessary to add !_.isFunction(this.settings.entityValidator)
and keep the _.isObject(this.settings.entityValidator)
for compatibility reasons
Tks
The problem comes when the adapter-mongoose is used with multiple services which doesnt have dependencies between each other.
Service A
module.exports = {
name: "testA",
mixins: [DbService],
adapter: new MongooseAdapter("mongodb://localhost/test"),
model: ModelForServiceA,
afterConnected() {
this.logger.info("Connected successfully A...");
}
}
Service B
module.exports = {
name: "testB",
mixins: [DbService],
adapter: new MongooseAdapter("mongodb://localhost/test"),
model: ModelForServiceB,
afterConnected() {
this.logger.info("Connected successfully B...");
}
}
if the mongodb server is down then Service B is going to report wrongly "Connected successfully B..." .
The reason was nailed to the connect function of MongooseDbAdapter :
connect() {
let conn
if (this.model) {
if (mongoose.connection.readyState != 0) {
this.db = mongoose.connection;
return Promise.resolve();
}
conn = mongoose.connect(this.uri, this.opts);
} else if (this.schema) {
conn = mongoose.createConnection(this.uri, this.opts);
this.model = conn.model(this.modelName, this.schema);
}
return conn.then(result => {
this.db = result.connection || result.db;
this.db.on("disconnected", function mongoDisconnected() {
/* istanbul ignore next */
this.service.logger.warn("Disconnected from MongoDB.");
}.bind(this));
});
}
while executing service B it checks for mongoose.connection.readyState
and after readyState 2 = connecting
the Promise resolves simply because the status is connecting.
However under normal connection behavior this function resolves only when the connection is established.
This provokes the function afterConnected
to be executed while there is no connection established.
Is there any different way to solve this issue without setting a dependency between services or using the schema instead of the model ?
Hi,
I'm new in Moleculer. I want to build my project with Moleculer and Cassandra.
Is there any examples to create a DB Service which connect to Cassandra?
Thank you.
I was looking a way to style responses before send em back thru api-gateway, but still have not found how.
Is it a hidden feature over there? or should it be a new GREAT feature?-
Hi, Is multiple query execute normal? 2 tables, executes total of 12 which is repeated. Just wondering what if this has 20+ tables then it would "probably" executes total of 120? Sorry for being such a noob :) Please, see log below:
> [email protected] dev /Volumes/KB/projects/t1/micro
> moleculer-runner --repl --hot services
[2018-09-08T00:41:27.667Z] INFO dev-macbook-pro.local-40732/BROKER: Moleculer v0.12.8 is starting...
[2018-09-08T00:41:27.670Z] INFO dev-macbook-pro.local-40732/BROKER: Node ID: dev-macbook-pro.local-40732
[2018-09-08T00:41:27.671Z] INFO dev-macbook-pro.local-40732/BROKER: Namespace: <not defined>
[2018-09-08T00:41:27.671Z] INFO dev-macbook-pro.local-40732/REGISTRY: Strategy: RoundRobinStrategy
[2018-09-08T00:41:27.685Z] INFO dev-macbook-pro.local-40732/REGISTRY: '$node' service is registered.
[2018-09-08T00:41:27.821Z] INFO dev-macbook-pro.local-40732/REGISTRY: 'api' service is registered.
[2018-09-08T00:41:27.822Z] INFO dev-macbook-pro.local-40732/API: Register route to '/'
[2018-09-08T00:41:27.855Z] INFO dev-macbook-pro.local-40732/API: API Gateway created!
[2018-09-08T00:41:27.857Z] INFO dev-macbook-pro.local-40732/REGISTRY: 'greeter' service is registered.
[2018-09-08T00:41:28.086Z] INFO dev-macbook-pro.local-40732/REGISTRY: 'profiles' service is registered.
[2018-09-08T00:41:28.087Z] INFO dev-macbook-pro.local-40732/REGISTRY: 'server' service is registered.
[2018-09-08T00:41:28.099Z] INFO dev-macbook-pro.local-40732/REGISTRY: 'users' service is registered.
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
[2018-09-08T00:41:28.217Z] INFO dev-macbook-pro.local-40732/API: API Gateway listening on http://0.0.0.0:3000
Executing (default): SELECT 1+1 AS result
Executing (default): SELECT 1+1 AS result
Executing (default): CREATE TABLE IF NOT EXISTS `account_profiles` (`id` INTEGER NOT NULL auto_increment , `user_id` INTEGER, `firstname` VARCHAR(255), `lastname` VARCHAR(255), `phone` VARCHAR(255), `gender` VARCHAR(255), `dob` DATETIME, `address` VARCHAR(255), `city` VARCHAR(255), `state` VARCHAR(255), `zipcode` VARCHAR(255), `timezone` VARCHAR(255), `avatar` VARCHAR(255), `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255), `email` VARCHAR(255), `deleted_at` DATETIME, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `account_profiles`
Executing (default): SHOW INDEX FROM `users`
Executing (default): SELECT 1+1 AS result
Executing (default): SELECT 1+1 AS result
Executing (default): CREATE TABLE IF NOT EXISTS `account_profiles` (`id` INTEGER NOT NULL auto_increment , `user_id` INTEGER, `firstname` VARCHAR(255), `lastname` VARCHAR(255), `phone` VARCHAR(255), `gender` VARCHAR(255), `dob` DATETIME, `address` VARCHAR(255), `city` VARCHAR(255), `state` VARCHAR(255), `zipcode` VARCHAR(255), `timezone` VARCHAR(255), `avatar` VARCHAR(255), `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL auto_increment , `name` VARCHAR(255), `email` VARCHAR(255), `deleted_at` DATETIME, `created_at` DATETIME, `updated_at` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `account_profiles`
Executing (default): SHOW INDEX FROM `users`
[2018-09-08T00:41:28.318Z] INFO dev-macbook-pro.local-40732/BROKER: ServiceBroker with 6 service(s) is started successfully.
mol $ q
mol $ [2018-09-08T00:41:31.157Z] INFO dev-macbook-pro.local-40732/API: API Gateway stopped!
[2018-09-08T00:41:31.159Z] INFO dev-macbook-pro.local-40732/BROKER: ServiceBroker is stopped successfully. Good bye.
The ctx
values are updated inside the update
hook but the ctx
changes are not reflected on the update
action. Hence, the data written to DB is not updated.
hooks: {
before: {
update: async function (ctx) {
/** await call here **/
ctx.params.data = { foo: 'bar' }
return
}
}
}
All default action in moleculer-db
try to call a before
hook from the schema. If the action result promise resolved, try to call after
hook from the schema.
{
name: "project",
settings: {...},
actions: { ... },
hooks: {
before: {
update(ctx) {
// It will be called before `update` action called.
// It can be return with Promise. If the returned promise
// rejected( or thrown an Error ), the `update` action
// won't be called!
}
},
after: {
create(ctx, model) {
// It will be called after a project created.
},
remove(ctx, model) {
// It will be called after a project removed.
}
}
},
methods: { ... }
}
Right now, if I define a class method inside the options
object of my model (say a search
method), it throws an exception when I try to access it through this.model.search
.
Am I missing something or using it incorrectly way?
Sequelize now throws a deprecation warning on starting even the basic example, saying symbols based operators are deprecated and symbols must be used instead
Hi,
We can populate by using a value from a particular field, how would we populate if we didn't have that field? E.g. I have two databases conversations and messages where messages references a conversation although if I wanted to get the messages for a conversation that is a different story.
Is there a way around this?
Thanks,
Jamie
In your README.md file you describe the Example with connection options
as follows:
new MongooseAdapter({
uri: "mongodb://db-server-hostname/my-db",
options: {
user: process.env.MONGO_USERNAME,
pass: process.env.MONGO_PASSWORD
server: {
socketOptions: {
keepAlive: 1
}
}
})
However, in your source code you access the options as opts
:
/**
* Connect to database
*
* @returns {Promise}
*
* @memberof MongooseDbAdapter
*/
connect() {
let uri, opts, conn;
if (_.isObject(this.opts) && this.opts.uri != null) {
uri = this.opts.uri;
opts = this.opts.opts; // opts or options???
} else {
uri = this.opts;
}
if (this.model) {
/* istanbul ignore next */
if (mongoose.connection.readyState != 0) {
this.db = mongoose.connection;
return Promise.resolve();
}
conn = mongoose.connect(uri, opts);
} else if (this.schema) {
conn = mongoose.createConnection(uri, opts);
this.model = conn.model(this.modelName, this.schema);
}
return conn.then(result => {
this.db = conn.connection || result.db;
this.db.on("disconnected", function mongoDisconnected() {
/* istanbul ignore next */
this.service.logger.warn("Disconnected from MongoDB.");
}.bind(this));
});
}
Please consolidate the documentation.
Thank you.
Examples of extend with custom actions in moleculer manual is:
const DbService = require("moleculer-db");
module.exports = {
name: "posts",
mixins: [DbService],
settings: {
fields: ["_id", "title", "content", "votes"]
},
actions: {
// Increment `votes` field by post ID
vote(ctx) {
return this.adapter.updateById(ctx.params.id, { $inc: { votes: 1 } });
},
// List posts of an author
byAuthors(ctx) {
return this.find({
query: {
author: ctx.params.authorID
},
limit: ctx.params.limit || 10,
sort: "-createdAt"
});
}
}
}
Examples of Sequelize Adapter in moleculer manual is:
"use strict";
const { ServiceBroker } = require("moleculer");
const DbService = require("moleculer-db");
const SqlAdapter = require("moleculer-db-adapter-sequelize");
const Sequelize = require("sequelize");
const broker = new ServiceBroker();
// Create a Sequelize service for `post` entities
broker.createService({
name: "posts",
mixins: [DbService],
adapter: new SqlAdapter("sqlite://:memory:"),
model: {
name: "post",
define: {
title: Sequelize.STRING,
content: Sequelize.TEXT,
votes: Sequelize.INTEGER,
author: Sequelize.INTEGER,
status: Sequelize.BOOLEAN
},
options: {
// Options from http://docs.sequelizejs.com/manual/tutorial/models-definition.html
}
},
});
broker.start()
// Create a new post
.then(() => broker.call("posts.create", {
title: "My first post",
content: "Lorem ipsum...",
votes: 0
}))
// Get all posts
.then(() => broker.call("posts.find").then(console.log));
If I want extend with custom actions use sequelize adapter, what should we do?
If you have subdocuments and try to update just one property it will remove all properties and add just the updated one.
The correct should be:
const sets = { 'prop': 'value', 'subdoc.prop1': 'value' }
and then
this.adapter.updateById(id, { $set: sets })
Refs:
https://docs.mongodb.com/manual/core/document/#dot-notation
https://www.npmjs.com/package/dot-object
The setting idField
is not working properly.
Steps to reproduce
'use strict'
const { ServiceBroker } = require('moleculer')
const DbService = require('moleculer-db')
const broker = new ServiceBroker()
// Create a DB service for `user` entities
broker.createService({
name: 'users',
mixins: [DbService],
settings: {
idField: 'myCustomIDField'
}
})
let newEntry = {
myCustomIDField: '123456789',
username: 'john',
name: 'John Doe',
status: 1
}
broker.start()
.then(() => broker.call('users.create', { ...newEntry }))
.then(() => broker.call('users.find', {}))
.then(res => console.log(res))
Exptected Result
[ { "username": "john",
"name": "John Doe",
"status": 1,
"myCustomIDField": "123456789'"} ]
Actual Result
[ { "myCustomIDField": "123456789",
"username": "john",
"name": "John Doe",
"status": 1,
"_id": "ch1O9ghyjFYStlpW" } ]
Problem Location
In actions.create
the entity is inserted without checking if it has any idField
as ID
moleculer-db/packages/moleculer-db/src/index.js
Lines 207 to 212 in 0abed0e
In methods.transformDocuments
the _id
field is not transformed into the idField
moleculer-db/packages/moleculer-db/src/index.js
Lines 537 to 541 in 0abed0e
Due to #21, we should remove adapter dependencies (mongodb
, mongoose
, sequelize
), because it doesn't work with different versions (when you use a version which is not exactly what adapter uses).
In this case, we can merge short adapter codes to the moleculer-db
repo.
Example to use DB service with mongoose adapter:
$ npm install moleculer-db mongoose
const DbService = require("moleculer-db");
const MongooseAdapter = DbService.Adapters.Mongoose;
const mongoose = require("mongoose");
module.exports = {
name: "posts",
mixins: [DBService],
adapter: MongooseAdapter("mongodb://..."),
model: mongoose.model("Post", mongoose.Schema({
title: { type: String },
content: { type: String },
votes: { type: Number, default: 0}
}))
}
Hi. I've encountered an issue when using fields
param through moleculer-web
s query: it seems it's not possible to pass only one field into fields
- that leads to an error
{
"name": "ValidationError",
"message": "Parameters validation error!",
"code": 422,
"type": "VALIDATION_ERROR",
"data": [
{
"type": "array",
"field": "fields",
"message": "The 'fields' field must be an array!"
}
]
}
To avoid that client can use something like http://my.host/endpoint?fields=foo&fields
but that doesn't look right.
That is caused by the fact that fields are defined as array and how the qs is parsing the query string.
Any thoughts on that?
Hi, i am using the sequelize adapter and when I was testing invalid connection option, the broker calls the started()
from the service DbService and does not stop, and if I create a DbService that merges and overrides the started
func and when I trigger a reject for n count of attempts the broker stops.
How do I handle such infinite loop connecting
to resolve? and does returning a reject does not trigger circuit breaker? or maybe can a broker stop loading that service and not halt everything and saying cant load all services.
Hi,
I'm fairly new to MoleculerDB, in my database I have a field like so participants: ["person 1 id", "person 2 id"]
how would I check if a id is in the array?
Thanks,
Jamie
Upgrade path -> looks straighforward
https://github.com/Automattic/mongoose/blob/master/migrating_to_5.md
With node and sequelize a can define all my models in another folder in different files and it's extremely comfortable.
Could I import my model.js and use it in service.js file? like model: myModel ? How to do it? I don't want to keep my models and logic in one trash file.
Hello,
I have not found any smart issue to manage this problem, the adapter changes the _id field as string, but I have also other ObjectId fields (some references to other collections) and they are not converted to string, so I need to call a toString() for doing other queries, but moleculer validation prevents to call service.get
using an object id or with null values.
My database has some optional references to other entities, so there are null values. I think that is not possible to manage directly, because validator throws an error...
Thanks to everyone :)
[2018-07-10T11:11:26.843Z] INFO mac-mini-di-andrea.local-20730/TEST: test.save STARTING...
[2018-07-10T11:11:26.853Z] INFO mac-mini-di-andrea.local-20730/TEST: test.save: { _id: '5b44945e0362e150fa37a60d', _idType: 'string', field: 000000000000000000000001, fieldType: 'object', fieldString: '000000000000000000000001', fieldStringType: 'string' }
[2018-07-10T11:11:26.857Z] INFO mac-mini-di-andrea.local-20730/TEST: test.save - forcing validation error, using an object for doing: broker.call("test.get", { _id: test.field });
Error occured! Parameters validation error!
When I stop the broker, the mongodb adapter was not stopped correctly, so although the test run successfully, it doesn't exit. I have to add the workaround code to my service:
async stopped() {
await this.adapter.client.close(true)
}
When I have a version in my service the clearCache doesn't work anymore.
The problem in the code
/**
* Clear cached entities
*
* @methods
* @returns {Promise}
*/
clearCache() {
var version = this.version ? this.version + '.' : '';
this.broker.broadcast(`cache.clean.${version}${this.name}`);
if (this.broker.cacher) {
// version is missing
this.broker.cacher.clean(`${version}${this.name}.*`);
}
return Promise.resolve();
},
Hi @icebob
I just start new project and has question about using database with your framework.
How use moleculer-db correctly? I will have many services and some service should take some information from mongo store, but collections can be different.
How i can see when use this module i should make many services for every collection. No way for use one db service?
when i use this code :
this.adapter.find({ $and: [{ from: { $lt: 1005 } }, { to: { $gt: 1005 } }] });
returns all of objects in db but when i run this query in robomongo give me one object that i want. please help me I want just one object to return to me
Currently there are populate
and entityValidator
which could be used for similar purpose, but it looks like kind of a hack to use it to transform entities.
The general idea here is to be able:
To transform input object to object like how it should look in DB. Example, user object, it might arrive with password
, but what we want to save to DB is salt
and hash
and not password field. This is possible with entityValidator
, but this sounds like a hack. - I was able to figure it out by looking into source code of entityValidator
since it is using .map on array, but it should use .every.
To transform output object to something else. Example to remove hash
and salt
fields could be achieved by filtering fields, which is cool, but in case we just want to transform it somehow differently its getting hard and using populate
for it is more like a hack.
Proposal is to:
Not sure what exactly needs to be done, but can write some proposal.
Hello,
I would like add a request for enhancement HTTP 2 support protocol
Congratulations for this framework!
Suppose I have a user and post table. The post will contain the user's foreign key
I want to retrieve a user record with all the users' post
AND
How can I change properties populate when merging?
I want to populate by author_id. however after merging I want to change author_id to author
origin
{
"title":"this is title post",
"author_id":{ ... }
}
expect
{
"title":"this is title post",
"author":{ ... }
}
http://[url]?query={"param1":"value1"}
I am trying to list using the query string to send a query filter but it's returning 422 - Unprocessable Entity
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.