Aws lambda 从AWS Lambda创建复杂的参数驱动查询?

Aws lambda 从AWS Lambda创建复杂的参数驱动查询?,aws-lambda,aws-appsync,Aws Lambda,Aws Appsync,查找//下面是问题部分句子,以查找问题所在的代码 我正在尝试使用AWS Lambda(连接到RDS Postgres服务器)作为数据源来实现AppSync。我想创建puKnowledgeFile查询,该查询将使用可选参数更新我的KnowledgeFile。如果客户端只提供了htmlText和properties作为参数,那么我的update查询应该只更新这两个字段 type Mutation { putKnowledgeFile( id: ID!, htm

查找
//下面是问题部分
句子,以查找问题所在的代码

我正在尝试使用AWS Lambda(连接到RDS Postgres服务器)作为数据源来实现AppSync。我想创建
puKnowledgeFile
查询,该查询将使用可选参数更新我的
KnowledgeFile
。如果客户端只提供了
htmlText
properties
作为参数,那么我的
update
查询应该只更新这两个字段

type Mutation {
    putKnowledgeFile(
        id: ID!,
        htmlText: String,
        plainText: String,
        properties: AWSJSON
    ): KnowledgeFile
}

type KnowledgeFile {
    id: ID!
    htmlText: String!
    plainText: String!
    properties: AWSJSON!
    lastDateTimeModified: AWSDateTime!
    dateTimeCreated: AWSDateTime!
}
以下是一段AWS Lambda代码:

exports.handler = async (event, context, callback) => {
  
  /* Connecting to Postgres */

  let data = null;
  let query = ``;
  let values = [];
  
  switch (event.info.fieldName) {
    case "putKnowledgeFile":
      if(event.arguments.htmlText === undefined &&
         event.arguments.plainText === undefined &&
         event.arguments.properties === undefined) {
        callback(`At least one argument except id should be provided in putKnowledgeFile request`);
      }

      // HERE IS THE PROBLEM PART
      query += `update knowledge_file`

      query += `
      set `;
      
      let index = 0;
      for (let fieldName in event.arguments) {
        if(arguments.hasOwnProperty(fieldName)) {
          const fieldValue = event.arguments[fieldName];
    
          if(index === 0) {
            query += `${fieldName}=$${index+1}`
            values.push(fieldValue);
          } else {
            query += `, ${fieldName}=$${index+1}`
            values.push(fieldValue);
          }
    
          index++;
        }
      }

      query += `
where knowledge_file.id = $${index+1};`;
      values.push(event.arguments.id);
      // HERE IS THE PROBLEM PART

        break;
    default:
      callback(`There is no functionality to process this field: ${event.info.fieldName}`);
      return;
  }
  
  let res = null;
  try {
    res = await client.query(query, values); // just sending created query
  } catch(error) {
    console.log("@client.query");
    console.log(error);
  }

  /* DisConnecting from Postgres */

  callback(null, res.rows);

};
基本上,该算法通过多个字符串串联来创建查询字符串。我认为它太复杂,而且容易出错是否有一种方法可以轻松地基于某些参数的存在/不存在创建动态查询?

以防万一,下面是我的PostgreSQL模式:

-- main client object for clients
CREATE TABLE client (
  id bigserial primary key,
  full_name varchar(255)
);

-- knowledge_file
create table knowledge_file (
  id bigserial primary key,
  html_text text,
  plain_text text,
  properties jsonb,
  last_date_modified timestamptz,
  date_created timestamptz,
  word_count varchar(50)
);

-- which client holds which knowledge file
create TABLE client_knowledge_file (
  id bigserial primary key,
  client_id bigint not null references client(id),
  knowledge_file_id bigint not null references knowledge_file(id) unique ON DELETE CASCADE
);

我知道这不是一个最佳的解决方案,可能无法完全回答您的问题,但我也遇到了类似的问题,这就是我解决问题的方式

  • 我创建了一个解析器管道
  • 在一个函数中,我使用
    select
    语句获取当前 记录
  • 在第二个函数中,我检查了字段(在您的例子中是
    htmlText
    properties
    )是否为空。如果为true,则使用
    ctx.prev.result
    值,否则使用新值)
  • 实例

    第一个解析器函数:

    {
        "version": "2018-05-29",
        "statements": [
            "select id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\" from knowledge_file where id = $ctx.args.Id"
        ]
    }
    
    #set($htmlText = $util.defaultIfNull($ctx.args.htmlText , $ctx.prev.result.htmlText))
    #set($properties = $util.defaultIfNull($ctx.args.properties , $ctx.prev.result.properties))
    
    
    {
        "version": "2018-05-29",
        "statements": [
            "update knowledge_file set html_text = $htmlText, plain_text = $ctx.args.plainText, properties = $properties, last_date_modified = CURRENT_TIMESTAMP, date_created = CURRENT_DATE where id = $ctx.args.Id returning id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\""
        ]
    }  
    
    第二个解析器功能:

    {
        "version": "2018-05-29",
        "statements": [
            "select id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\" from knowledge_file where id = $ctx.args.Id"
        ]
    }
    
    #set($htmlText = $util.defaultIfNull($ctx.args.htmlText , $ctx.prev.result.htmlText))
    #set($properties = $util.defaultIfNull($ctx.args.properties , $ctx.prev.result.properties))
    
    
    {
        "version": "2018-05-29",
        "statements": [
            "update knowledge_file set html_text = $htmlText, plain_text = $ctx.args.plainText, properties = $properties, last_date_modified = CURRENT_TIMESTAMP, date_created = CURRENT_DATE where id = $ctx.args.Id returning id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\""
        ]
    }  
    

    由于您可以直接将AppSync API连接到RDS,因此使用Lambda连接到RDS实例有什么具体原因吗?您的意思是使用Aurora无服务器数据API?那么,我需要在映射模板中执行类似的逻辑,而且使用JS而不是VTL似乎更方便。我错了吗?是的,我就是这个意思。您如何在RDS中定义这些?这些字段可以为空吗?请您澄清一下,“这些”是什么意思?对不起。我的意思是,您如何在RDS表模式中定义这些字段(
    htmlText
    &
    properties
    )?