My graphql queries work with the local DB file but while trying to connect to MongoDB it doesn't work as expected.
mongo.js
require("dotenv").config();
const mongoose = require("mongoose");
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
throw new Error(
"Please define the MONGODB_URI environment variable inside .env.local"
);
}
/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections from growing exponentially
* during API Route usage.
*/
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function dbConnect() {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const opts = {
bufferCommands: false,
};
cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
return mongoose;
});
}
cached.conn = await cached.promise;
return cached.conn;
}
module.exports = dbConnect;
MONGODB_URI=mongodb+srv://xxxx:xxxx#cluster0.yxbw7.mongodb.net/?retryWrites=true&w=majority
graphql query to get all the products:
exports.typeDefs = gql`
type Query {
products: [Product!]!
}
type Product {
id: ID!
name: String!
description: String!
price: Float!
image: String!
}
`;
Resolvers:
const { Product } = require("../models/Product");
exports.Query = {
products: async (parent, args, context) => {
let products = await Product.find({}).exec();
return products;
},
};
The DB has data in it but still making the query,
query{
products {
description
id
name
price
image
}
}
It returns an empty product array,
{
"data": {
"products": []
}
}
Something seems wrong with MongoDB to connect with graphql, the queries work with the local DB file which has a dummy object product data.
Related
I am new to using Graphql and MongoDB. I am trying to insert data from an existing javascript file where the data has been defined. I was trying to use a mutation in order to achieve this but I have no clue what I'm really doing. Any help would be nice.
const dotenv = require('dotenv');
dotenv.config();
const { ApolloServer, gql } = require('apollo-server');
const { MongoClient } = require('mongodb');
const items = require('./itemsListData');
const typeDefs = gql`
type Query {
items:[Item!]!
}
type Item{
id:ID!,
name:String!,
aisle:String!,
bay:String!,
price:Float!,
xVal:Int!,
yVal:Int!
}
type Mutation {
createItem(name: String!, aisle: String!): Item!
}
`;
console.log(items)
const resolvers = {
Query: {
items:() => items,
},
Item:{
id: ( { _id, id }) => _id || id,
},
Mutation: {
createItem: async(_, { name }, { db }) => {
// name:String!, bays:[Bay!]!, xStartVal:Int!, xEndVal:Int!, yStartVal:Int!, yEndVal:Int!
const newItem = {
items
}
// insert Item object into database
const result = await db.collection('Items').insert(newItem);
console.log("This is the result " + result);
return result.ops[0]; // first item in array is the item we just added
}
}
};
const start = async () => {
const client = new MongoClient("mongodb+srv://admin:admin#quickkartcluster.o0bsfej.mongodb.net/test", { useNewUrlParser: true, useUnifiedTopology: true });
await client.connect();
const db = client.db("QuickKart");
const context = {
db,
}
const server = new ApolloServer({
typeDefs,
resolvers,
context,
introspection: true
});
// The `listen` method launches a web server.
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
}
start();
here is my javascript data file
https://pastebin.com/wvGANBgR
I am unsure of how to change/update the data in my database through react.
My database:
const Package = new mongoose.Schema({
packageID = {type: String},
packageStatus = {type: String, enum: [packed, delivered, received], default: 'packed' },
})
how do I refer to packageStatus and their enum values in react/class component? How should I call them?
The default value is 'packed', I want to change it to 'delivered' when a button is clicked (no text fields involved).
class PackageStatus extends React.Component {
constructor(){
super()
this.state = {
packageStatus: 'packed'
}
this.updateStatus = this.updateStatus.bind(this);
}
updateStatus(){
this.setState =({
packageStatus: 'delivered'
}
)
render(){
return (
<div?
<button onClick={()=> packageStatus(this)}>Update Status</button>
</div>
)
}
}
export default PackageStatus
The code above changes the text displayed but not the status in the database, so how do I change the data in the database?
Next, I would want to display text depending on what the status in the database is. I'm not sure how to link isDelivered to the condition of the database.
For example
class Status extends Component {
constructor(props) {
super(props);
this.state = {
isDelivered: true
};
}
render() {
let { isDelivered } = this.state;
let status;
if (isDelivered) {
status = <h1>Delivered<h1>
} else {
status = <h1>Packing in progress<h1>
}
return (
<div>
{status}
</div>
);
}
}
export default Status;
Any help will be greatly appreciated! Thank you for your time
Well interfacing, a frontend framework like REACT with a database, an easier approach would be create apiEndpoints of which you would use make fetch or axios to make httpRequests which communicates to these endpoints, in turn communicate with the database to give you your desired response. A solution approach to your problem is as follows:
Create the schema using mongoose in node
const mongoose = require('mongoose')
const { Schema } = mongoose
const PackageSchema = new Schema({
packageID: {
type: String,
},
packageStatus: {
type: String,
enum: ["packed", "delivered", "received"],
default: 'packed'
}
})
module.exports = mongoose.model('package',PackageSchema)
Create the apiEndpoints or routes to interface this schema with FrontEnd(React) and Backend(eg; mongodb)
const express = require('express');
const router = express.Router();
require('dotenv').config()
const package = require('../model/packageModel');
router.get('/allpackages', async(req, res) => {
try{
const getAllPackages = await package.find();
res.json(getAllPackages);
}catch(err){
res.json({
message: err
})
}
})
router.post('/addPackage',async(req, res) => {
const pack = new package({
packageID: req.body.packageID,
packageStatus: req.body.packageStatus
})
try{
const savedPost = await pack.save();
res.json(savedPost);
}catch(err){
res.json({
message: err
})
}
})
router.patch('/updatePackageStatus', async (req, res) => {
try {
const updatePackageStatus = await package.updateOne(
{ _id: req.body.packageID },
{
$set: {
packageStatus: req.body.packageStatus
}
}
)
res.json(updatePackageStatus)
}catch (err) {
res.json({
message: err
})
}
})
module.exports = router;
Use POSTMAN or any other of choice to test endpoints with schema, and database, to see if you get the desired results. After testing out the above, with POSTMAN, all desired operations work as expected, and you should have no problem, interfacing it with any Frontend Framework(Angular, React, Vue) now.
GET http://localhost:3000/package/allpackages
POST http://localhost:3000/package/addPackage
PATCH http://localhost:3000/package/updatePackageStatus
sample screenshot shown below
fetch api Endpoints via postman
I want to create a local gatsby plugin to index graphql querys in elastic app search.
My problem is, how I can get the articles with a graphql query as an array.
I need a structure like this:
const documents = [
{
id: 'INscMGmhmX4',
url: 'https://www.youtube.com/watch?v=INscMGmhmX4',
title: 'The Original Grumpy Cat',
body: 'A wonderful video of a magnificent cat.'
},
{
id: 'JNDFojsd02',
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
title: 'Another Grumpy Cat',
body: 'A great video of another cool cat.'
}
]
This is my query I want to index from Strapi:
const myQuery = `
{
allStrapiKbArticles {
edges {
node {
id
title
content
}
}
}
}
`
Here is my current code of the gatsby-node.js file:
const chunk = require('lodash.chunk');
const report = require('gatsby-cli/lib/reporter');
const AppSearchClient = require ('#elastic/app-search-node');
let activity = report.activityTimer(`Indexing to ElasticSearch`);
exports.onCreateDevServer = async function (
{ graphql },
{ baseUrlFn, apiKey, queries, chunkSize = 1000 }
) {
activity.start();
const client = new AppSearchClient(undefined, apiKey, baseUrlFn)
setStatus(activity, `${queries.length} queries to index`);
const jobs = queries.map(async function doQuery(
{ engineName: engineName, query, transformer = identity, indexConfig },
i
) {
if (!query) {
report.panic(
`failed to index to Elastic. You did not give "query" to this query`
);
}
setStatus(activity, `query ${i}: executing query`);
const result = await graphql((query)
).then(result => console.log(result))
activity.end();
})
}
Error: TypeError: graphql is not a function (const result = await graphql((query))
I am using Apollo-server-express and Graphql-tools. I have been all over the Graphql-tools documentation and I can't get this to work. I'm trying to get my schema.graphql file to import as my typeDefs. It seems like Graphql-tools should be making this easy, but something isn't falling into place.
index.js
const { ApolloServer } = require("apollo-server-express");
const { makeExecutableSchema } = require('#graphql-tools/schema');
const express = require("express");
const { join } = require("path");
const { loadSchema } = require("#graphql-tools/load");
const { GraphQLFileLoader } = require("#graphql-tools/graphql-file-loader");
const { addResolversToSchema } = require("#graphql-tools/schema");
const app = express();
const resolvers = {
Query: {
items: (parent, args, ctx, info) => {
return ctx.prisma.item.findMany();
},
},
Mutation: {
makeItem: (parent, args, context, info) => {
const newItem = context.prisma.item.create({
data: {
...args,
price: parseInt(Math.ceil(args.price * 100)),
},
});
return newItem;
},
deleteItem: (parent, args, context, info) => {
return context.prisma.item.delete({
where: {
id: args.id,
},
});
},
},
};
const schemaSource = loadSchemaSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const schema = makeExecutableSchema({
typeDefs: schemaSource,
resolvers,
});
const server = new ApolloServer({
schema,
resolvers,
});
server.applyMiddleware({ app });
app.listen(
{ port: 4000 },
() =>
console.log(
`🌎 => Backend server is now running on port http://localhost:4000`
)
);
schema.graphql
type Query {
items: [Item!]!
}
type Mutation {
makeItem(
piece: String!
image: String!
identifier: String!
price: Float!
itemNumber: Int!
): Item!
deleteItem(id: ID!): Item!
}
type Item {
id: ID!
piece: String!
image: String!
identifier: String!
price: Int!
itemNumber: Int!
}
In its current state I am getting an error that says: "Error: typeDefs must be a string, array or schema AST, got object"
As I understand it makeExecutableSchema should be doing all the necessary steps, like changing the schema into a string. I can't seem to figure out what is going on here and any help would be greatly appreciated.
loadSchemaSync will load a GraphQLSchema object using the provided pointer. You should use loadTypedefsSync instead.
const sources = loadTypedefsSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const typeDefs = sources.map(source => source.document)
const server = new ApolloServer({ typeDefs, resolvers })
If you want to use loadSchema, you don't need to use makeExecutableSchema because your schema has already been created. So you would do this instead as shown in the docs:
const schema = loadSchemaSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const resolvers = {...};
const schemaWithResolvers = addResolversToSchema({
schema,
resolvers,
});
const server = new ApolloServer({ schema: schemaWithResolvers })
I`m trying to query my business network using buildQuery but it always returns an empty array.
My code is as follows.
This is the connection.js file:
module.exports = {
BusinessNetworkConnection : require('composer-client').BusinessNetworkConnection,
cardName : '',
connection: {},
connect : function() {
var cardType = { type: 'composer-wallet-filesystem' }
this.connection = new this.BusinessNetworkConnection(cardType);
return this.connection.connect(this.cardName);
},
disconnect : function(callback) {
this.connection.disconnect();
}
};
This is my query.js file which being invoked to get results:
const connection = require('./connection');
const getContacts = async (cardName,companyID) => {
connection.cardName = cardName;
try {
await connection.connect();
main();
} catch (error) {
main(error);
}
async function main(error) {
if (error) { return new Error("Ops Error: ",error) };
const statement = 'SELECT org.finance.einvoice.participant.Company WHERE (participantId == _$companyID)'
const query = await connection.connection.buildQuery(statement);
const company = await connection.connection.query(query, { companyID }).catch(err => {return new Error(err)});
await connection.connection.disconnect().catch(err => new Error(err));
console.log(company);
return company;
};
};
module.exports = {
getContacts
};
The expected behavior from getContacts() is to return an asset from business network but it actually returns an empty array.
Current versions: composer-cli 0.20 , composer-playground 0.20 , composer-client 0.20 , composer-common 0.20 and fabric-dev-server 1.2 .
i found the solution for this issue.
i was using card which was not allowed to perform queries. However, when i used the admin card it returned with results.
other way is to allow participants to issue queries in permission.acl file.