I am currently using prisma 2.20.1 on a project running postgres.
On their doc they say to import PrismaClient and instantiate it throughout the application.
However, coming from other use cases, where you connect to the db only once, feels weird on every route (different file and directory as my project structure is set to), to instantiate, and (connect to the db again?).
My point is, is there a way to centralize the database connection in one file, and use its instance throughout the application? Would it be safe to do that? Any consequences?
My idea is something like:
// database.ts
import { PrismaClient } from '#prisma/client';
class Database {
constructor() {
this.db = new PrismaClient();
}
}
const database = new Database();
export default new Database();
Then across the routes files
// specificRouteFile.ts
import db from 'database';
// run queries...
db.SomeTable.create({})
Inspired by #Mahmoud Abdelwahab I created a TypeScript (instantiate) version:
// lib/prisma.ts
import { PrismaClient } from '#prisma/client';
interface CustomNodeJsGlobal {
prisma: PrismaClient;
}
declare const global: CustomNodeJsGlobal;
const prisma = global.prisma || new PrismaClient();
if (process.env.NODE_ENV === 'development') global.prisma = prisma;
export default prisma;
After creating this file, you can now import this PrismaClient instance anywhere. You can get in-depth information about instance PrismaClient here.
import prisma from '../lib/prisma';
You can create and initialize Prisma in a file and then import it across the different files.
//lib/prisma.js
import { PrismaClient } from "#prisma/client";
const prisma = new PrismaClient();
export default prisma;
Then in a different file for example, just do
import prisma from "./lib/prisma"
const posts = prisma.posts.findMany({})
Related
One of my schema.prisma's file is wrote like this:
generator client {
provider = "prisma-client-js"
output = "./generated/own_database"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Employee {
...
}
And I have another one, which is like this:
generator client {
provider = "prisma-client-js"
output = "./generated/another_database"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL_2")
}
model Costs {
cod_center_cost Int #id
description String? #db.VarChar(100)
status Boolean?
classification Int?
}
...
I have a model that needs to have a relation to another model, but how can I refer an another file's model?
Splitting Prisma's schema file is not officially possible yet.
However there are some community provided solutions like Aurora which provides you functionality to split prisma schemas and import them.
Here's the Official GitHub Issue where splitting schema file is being tracked by Prisma Team.
Given a MEVN stack using Nestjs, MongoDB(mongoose) I am working to setup server-side pagination. My approach is to use the mongoose-aggregate-paginate-v2, but I have not been able to distill what I need from my research1 to make this work within the framework of Nestjs(typescript) and mongoose. Thanks for the assist..
Following documentation on Nestjs mongoose models, and mongoose-aggregate-paginate-v2 setup, I have the following:
contact.provider.ts
import mongoose, { Connection, AggregatePaginateResult, model } from "mongoose";
import { ContactSchema } from "./contact.schema";
import aggregatePaginate from "mongoose-aggregate-paginate-v2";
import { IContact } from "./interfaces/contact.interface";
// notice plugin setup:
ContactSchema.plugin(aggregatePaginate);
// is this correct ?
interface ContactModel<T extends Document> extends AggregatePaginateResult<T> {}
// how to create model for factory use ?
export const ContactModel: ContactModel<any> = model<IContact>('Contact', ContactSchema) as ContactModel<IContact>;
export const contactProvider = [
{
provide: 'CONTACT_MODEL',
useFactory: (connection: Connection) => {
// how to instantiate model ?
let model = connection.model<ContactModel<any>>('Contact', ContactSchema);
return model;
},
inject: ['DATABASE_CONNECTION'],
},
];
I am between reading the Nestjs documentation, mongoose documentation, and typescript documentation. Somewhere along this path there is a way to provide the aggregatePaginate method on my Contact model, so that I can call like:
contact.service.ts
// Set up the aggregation
const myAggregate = this.contactModel.aggregate(aggregate_options);
const result = await this.contactModel.aggregatePaginate(myAggregate, options); // aggregatePaginate does not exist!
Review code in progress - available on this branch.
Research
Mongoose the Typescript way…?
Complete Guide for using Typescript in Mongoose with lean() function
Complete guide for Typescript with Mongoose for Node.js
MosesEsan/mesan-nodejs-crud-api-with-pagination-filtering-grouping-and-sorting-capabilities
Node.js API: Add CRUD Operations With Pagination, Filtering, Grouping, and Sorting Capabilities.
API Paging Built The Right Way
SO: Mongoose Plugins nestjs
SO: Pagination with mongoose and nestjs
There is a conflict between NestJs and mongoose-aggregate-paginate-v2 and mongoose-paginate-v2 because those plugins are using #types/mongoose, so, NestJS has conflicts if you use #types/mongoose.
I tell you this because i was trying the same thing and figure it out that is not posible to implement mongoo-aggreate-paginate-v2/mongoose-paginate-v2 till Nestjs solve the issues with #types/mongoose.
I can recommend you make a custom function by your own to do that or use https://www.npmjs.com/package/mongoose-paginate because that plugin does not require #types/mongoose.
I have the following model:
import { Model } from '#vuex-orm/core'
export class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(null),
name: this.attr('')
}
}
}
and when I try to do this:
User.insert({
data: { id: 1, name: 'John' }
})
I get the following error:
Uncaught (in promise) TypeError: Class constructor User cannot be invoked without 'new'
Any idea what is the problem? This code is from the documentation, so I'm confused a little bit.
as I can see you are missing the registration of the model in the database at the beginning of the application.
You have to implement your vuex store with the corresponding plugin
EXAMPLE:
import Vue from 'vue'
import Vuex from 'vuex'
import VuexORM from '#vuex-orm/core'
import User from '#/models/User'
import Post from '#/models/Post'
Vue.use(Vuex)
// Create a new instance of Database.
const database = new VuexORM.Database()
// Register Models to Database.
database.register(User)
database.register(Post)
// Create Vuex Store and register database through Vuex ORM.
const store = new Vuex.Store({
plugins: [VuexORM.install(database)]
})
export default store
You now have good documentation in this regard
I hope I have helped you, greetings
I am trying to add some support for Apache Phoenix to ActiveJDBC. I am using the ActiveJDBC simple-example project as test, and making changes to a clone of ActiveJDBC 2.0-SNAPSHOT (latest from github).
So far in ActiveJDBC 2.0-SNAPSHOT I have:
created a PhoenixDialect class in org.javalite.activejdbc.dialects to
Override the insert method (Phoenix uses UPSERT)
added an if stanza to the getDialect(String dbType) method in
Configuration
In the simple-example project I have:
added the phoenix-client as a dependency (we are using Phoenix as
part of HortonWorks HDP 2.5.3.0 on HBase 1.1.2.2.5)
set the database.properties with Phoenix values
created the relevant tables in Phoenix manually (db-migrate does
not work for obvious reasons)
However, the database dialect is not being recognized, and is, I believe, defaulting to the DefaultDialect as I get a Phoenix error on the use of "INSERT" which is not recognized in the Phoenix grammar. Phoenix grammar
Are there additional steps I am missing when adding support for an additional dialect?
I also suspect the Phoenix jdbc driver may not support a getDbName() type method, the Phoenix driver, when asked for getPropertyInfo() returns EMPTY_INFO, see PhoenixEmbeddedDriver
If the driver does not return the DbName, is there a workaround?
It might be worth mentioning we are successfully interacting with Phoenix using standard Java jdbc classes (PreparedStatement and all that good stuff), but ActiveJDBC is much more elegant and we would like to use it.
Pieces of what we have so far:
PhoenixDialect
import java.util.Iterator;
import java.util.Map;
import org.javalite.activejdbc.MetaModel;
import static org.javalite.common.Util.join;
public class PhoenixDialect extends DefaultDialect {
#Override
public String insert(MetaModel metaModel, Map<String, Object> attributes) {
StringBuilder query = new StringBuilder().append("UPSERT INTO ").append(metaModel.getTableName()).append(' ');
if (attributes.isEmpty()) {
appendEmptyRow(metaModel, query);
} else {
boolean addIdGeneratorCode = (metaModel.getIdGeneratorCode() != null
&& attributes.get(metaModel.getIdName()) == null); // do not use containsKey
query.append('(');
if (addIdGeneratorCode) {
query.append(metaModel.getIdName()).append(", ");
}
join(query, attributes.keySet(), ", ");
query.append(") VALUES (");
if (addIdGeneratorCode) {
query.append(metaModel.getIdGeneratorCode()).append(", ");
}
Iterator<Object> it = attributes.values().iterator();
appendValue(query, it.next());
while (it.hasNext()) {
query.append(", ");
appendValue(query, it.next());
}
query.append(')');
}
return query.toString();
}
}
Configuration
public Dialect getDialect(String dbType) {
Dialect dialect = dialects.get(dbType);
if (dialect == null) {
if (dbType.equalsIgnoreCase("Oracle")) {
dialect = new OracleDialect();
}
else if (dbType.equalsIgnoreCase("Phoenix")) {
dialect = new PhoenixDialect();
}
else if (dbType.equalsIgnoreCase("MySQL")) {
dialect = new MySQLDialect();
}
database.properties
development.driver=org.apache.phoenix.jdbc.PhoenixDriver
development.username=anything
development.password=anything
development.url=jdbc:phoenix:hdp-c21:2181:/hbase-unsecure
Here is a branch that was used to integrate SQLServer with new Dialect, test suite and other related stuff:
https://github.com/javalite/activejdbc/tree/sql_server_integration
Here is a branch for h2:
https://github.com/javalite/activejdbc/commits/h2integration
Things may have changed since then, but this branch will give you good guidance. Best if you fork the project, and when done submit your work as a pull request.
Do I have to have a domain object to query mongodb?
What if I just want some raw data to be displayed? What would be the syntax to query mongodb from my controller?
I tried
"def var = db.nameOfMyCollection.find()"
but it says no such property as db in my controller class.
I know that my application is connecting to the database because I am monitoring mongo server log and it increases the number of connections by one when I launch my grails app.
Assuming you have added mongodb java driver dependency in build config and refreshed your dependencies.
Create a grails service named MongoService.groovy and put the following code.
Dont forget to import mongodb
package com.organisation.project
import com.mongodb.*
class MongoService {
private static MongoClient mongoClient
private static host = "localhost" //your host name
private static port = 27017 //your port no.
private static databaseName = "your-mongo-db-name"
public static MongoClient client() {
if(mongoClient == null){
return new MongoClient(host,port)
}else {
return mongoClient
}
}
public DBCollection collection(collectionName) {
DB db = client().getDB(databaseName)
return db.getCollection(collectionName)
}
}
We can now use this MongoService in our controllers or other services.
Now you can do following stuff in your controller.
Dont forget to import mongodb.DBCursor
package com.organisation.project
import com.mongodb.DBCursor
class YourControllerOrService {
def mongoService //including Mongo service
def method(){
def collection = mongoService.collection("your-collection-name")
DBCursor cursor = collection.find()
try{
while(cursor.hasNext()){
def doc = cursor.next()
println doc //will print raw data if its in your database for that collection
}
}finally {
cursor.close()
}
}
}
For more info Refer mongodb java docs
Ok, solved.
This is how you go about accessing the database.
import com.mongodb.*
MongoClient mongoClient = new MongoClient("localhost", 27017)
DB db = mongoClient.getDB("db");
I actually solved it using Java and then pasted it into groovy and it works there as well which shouldn't come as a surprise. The difference is that in Java you actually have to import the jar driver, but in Grails, you install the Mongo GORM plugin.
Assuming you are using the MongoDB GORM Plugin, if you have domain classes in your grails application, you can use them as you would with any relational db backend.
However, per this documentation, you can access the low-level Mongo API in any controller or service by first declaring a property mongo, just as you would a service, then getting the database you are targeting:
def mongo
def myAction = {
def db = mongo.getDB("mongo")
db.languages.insert([name: 'Groovy'])
}