Git Product home page Git Product logo

Comments (12)

acarl005 avatar acarl005 commented on June 15, 2024

@praseedasathaye Which version on join-monster are you on? I've added some additional validations recently, so more helpful error messages are thrown in cases on configuration errors. Make sure you're on join-monster v1.0.1 and try again. If joinMonster is called in a resolver on a field that is a CashExpense type, then you must add sqlTable to the CashExpense type. Please make sure that is defined.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

I took the latest "join-monster": "^v1.0.1-beta.1"

And also added below (sqltable and uniquekey) to CashExpense

const CashExpense = new GraphQLObjectType({
  description: 'Cash Expense Items',
  sqlTable: 'XXX',
  uniqueKey: 'EXPENSE_ID',
  name: 'CashExpense',
  fields: () => ({
    Count: {
      type: GraphQLInt,
      description: 'Count of Cash Expense Items',
      sqlExpr: table => `(SELECT count(*) FROM XXX WHERE EXPENSE_SOURCE = 'CASH')`
    },
    ExpenseItem: {
      type: new GraphQLListExpense),
      description: 'List of cash expense items.',
    }
  })
})

Now it gives me this error. I dont have any join condition between the tables here. The query is a separate query to get count.

{ AssertionError: If an Object type maps to a SQL table and has a child which is another Object type that also maps to a SQL table, you must define "sqlJoin", "sqlBatch", or "junctionTable" on that field to tell joinMonster how to fetch it. Check the "ExpenseItem" field on the "CashExpense" type.
    at getGraphQLType (/node_modules/join-monster/dist/queryASTToSqlAST.js:95:28)
    at handleSelections (/node_modules/join-monster/dist/queryASTToSqlAST.js:218:9)
    at handleTable (/node_modules/join-monster/dist/queryASTToSqlAST.js:208:5)
    at getGraphQLType (/node_modules/join-monster/dist/queryASTToSqlAST.js:97:5)
    at Object.queryASTToSqlAST (/node_modules/join-monster/dist/queryASTToSqlAST.js:35:3)
    at /node_modules/join-monster/dist/index.js:9:29
    at Generator.next (<anonymous>)
    at step (/node_modules/join-monster/dist/index.js:85:191)
    at /node_modules/join-monster/dist/index.js:85:437
    at /node_modules/join-monster/dist/index.js:85:99
    at joinMonster (/node_modules/join-monster/dist/index.js:19:17)
    at resolve (/schema/QueryRoot.js:34:16)
    at resolveOrError (/node_modules/graphql/execution/execute.js:454:12)
    at resolveField (/node_modules/graphql/execution/execute.js:445:16)
    at /node_modules/graphql/execution/execute.js:252:18
    at Array.reduce (native)

from join-monster.

acarl005 avatar acarl005 commented on June 15, 2024

@praseedasathaye The Count field is not the problem here, that looks fine. The error is regarding the ExpenseItem field. This field required either a join or batch condition.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

ExpenseItem is just a list of type Expense and does not have any join or batch.

ExpenseItem: {
      type: new GraphQLList(Expense),
      description: 'List of cash expense items.',
    }

from join-monster.

acarl005 avatar acarl005 commented on June 15, 2024

The Expense type also has sqlTable set. Therefore Join Monster is expecting to fetch data for it in a SQL table, and it must do so by JOINing or beginning another batch request . If the Expense is not supposed to come from a SQL table, you must remove the sqlTable property.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

But the ExpenseItem Type is just collection of Expense Type. There is no join or batch required here. Expense has the required join for the table to get data. Do I need to resolve ExpenseItem using join-monster just like you do in QueryRoot (see below)? Below you have list or collection of Sponsor Type. Similarly I have list of Expense Type but this one is not at QueryRoot level but inside the Type ExpenseItem.
My use case is get the count of Expenses along with the list of Expenses. For this I am wrapping the Expense Type with the CashExpense Type which gives the count in a separate query and gets list from the Expense Type.

sponsors: {
      type: new GraphQLList(Sponsor),
      resolve: (parent, args, context, resolveInfo) => {
        // use the callback version this time
        return joinMonster(resolveInfo, context, (sql, done) => {
          knex.raw(sql)
          .then(data => done(null, data))
          .catch(done)
        }, options)
      }
    }

from join-monster.

acarl005 avatar acarl005 commented on June 15, 2024

Do I need to resolve ExpenseItem using join-monster just like you do in QueryRoot?

No.

Expense has the required join for the table to get data.

This is not the case. sqlJoin is never defined on a type. It is defined on a field. You may have defined sqlJoin on another field which had the type Expense, but this is only for that particular field. Joins cannot be defined once per type because the join condition can be different between any two types. This is what you must do:

const CashExpense = new GraphQLObjectType({
  description: 'Cash Expense Items',
  sqlTable: 'XXX',
  uniqueKey: 'EXPENSE_ID',
  name: 'CashExpense',
  fields: () => ({
    Count: {
      type: GraphQLInt,
      description: 'Count of Cash Expense Items',
      sqlExpr: table => `(SELECT count(*) FROM XXX WHERE EXPENSE_SOURCE = 'CASH')`
    },
    ExpenseItem: {
      type: new GraphQLList(Expense),
      description: 'List of cash expense items.',
      sqlJoin: (table1, table2) => //define the join condition here
    }
  })
})

The sqlJoin will probably be exactly the same as when you did the join on a single Expense type. But keep in mind that join monster cannot assume the joins between any two types will be the same.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

May be I confused you. Sorry about that. There is no join condition required for the field ExpenseItem in CashExpense Type. ExpenseItem field is just a collection of Expense Type.

Should I remove the sqlTable and UniqueKey in that case as there is no join required for any fields in CashExpense.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

And when I removed the sqlTable and uniqueKey from ExpenseItem it gave me this error.

      "message": "Must call joinMonster in a resolver on a field where the type is decorated with \"sqlTable\".",
const CashExpense = new GraphQLObjectType({
  description: 'Cash Expense Items',
  name: 'CashExpense',
  fields: () => ({
    Count: {
      type: GraphQLInt,
      description: 'Count of Cash Expense Items',
      sqlExpr: table => `(SELECT count(*) FROM EXM_EXPENSES WHERE EXPENSE_SOURCE = 'CASH')`
    },
    ExpenseItem: {
      type: new GraphQLList(Expense),
      description: 'List of cash expense items.'
    }
  })
})

export default CashExpense

from join-monster.

acarl005 avatar acarl005 commented on June 15, 2024

Oh now I see. Then ExpenseItem is not really related to the parent CashExpense? In that case, does it even make sense to put a list of ExpenseItems inside the CashExpense? Why not make it a separate field?

{
  cashItems { 
    Count
  }
  expenseItems {
    ExpenseId
    PersonId
    #...
  }
}

If you do so, you'll need to put sqlTable and uniqueKey back on that type and write a resolver on that field that call joinMonster again, just as the Sponsor type does in the example.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

I will try this. This should work for me.

from join-monster.

praseedasathaye avatar praseedasathaye commented on June 15, 2024

Tried adding the count to the Connection and it gives me an error. Also it does not print the arguments in the below block which is passed in the graphql query

onst connectionConfig = { nodeType: Expense }
if (PAGINATE === 'offset') {
  connectionConfig.connectionFields = {
    Count: {
      type: GraphQLInt,
      description: 'Count of Cash Expense Items',
      sqlExpr: table => `(SELECT count(*) FROM EXM_EXPENSES WHERE EXPENSE_SOURCE = 'CASH')`,
      resolve: async (parent, args, context, resolveInfo) => {
          console.log("print in the connection: " + args.expenseSource)
          return joinMonster(resolveInfo, context, sql => dbCall(sql, knex, context), options)
        } 
    }
  }
}
const { connectionType: ExpenseConnection } = connectionDefinitions(connectionConfig)

export { Expense, ExpenseConnection }

Error that I get is.

{ AssertionError: Must call joinMonster in a resolver on a field where the type is decorated with "sqlTable".
    at Object.queryASTToSqlAST (node_modules/join-monster/dist/queryASTToSqlAST.js:37:20)
    at node_modules/join-monster/dist/index.js:9:29
    at Generator.next (<anonymous>)
    at step (node_modules/join-monster/dist/index.js:85:191)
    at node_modules/join-monster/dist/index.js:85:437
    at node_modules/join-monster/dist/index.js:85:99
    at joinMonster (node_modules/join-monster/dist/index.js:19:17)
    at schema/Expense.js:167:18
    at Generator.next (<anonymous>)
    at step (schema/Expense.js:50:191)
    at schema/Expense.js:50:437
    at schema/Expense.js:50:99
    at resolve (schema/Expense.js:165:7)
    at resolveOrError (node_modules/graphql/execution/execute.js:454:12)
    at resolveField (node_modules/graphql/execution/execute.js:445:16)
    at node_modules/graphql/execution/execute.js:252:18
  message: 'Must call joinMonster in a resolver on a field where the type is decorated with "sqlTable".',
  locations: [ { line: 17, column: 5 } ],
  path: [ 'items', 'Count' ] }

from join-monster.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.