MySQLデータベースにどのようにシンプルでエレガントなアクセスをnodejs

I.背景の問題

nodejsの誕生は、そのような明確なkoa2卵としてなどのWebフレームワークが多数登場しているので、フロントエンドは、もはや自分自身のサーバー側のロジックを制御することができ、バックエンドに頼ることはできません。生徒の発達の前端部の後端部の元の位置には今も、高速な書き込みその袖をロールアップして、プロジェクトをやっている数週間のフロントエンド、すべてが自分を取得し、どのような効率のバックエンド。

様々なフレームワークは、CRUD操作を簡素化するために、独自のインタフェースの一部を提供し、まだ開発プロセス、多くの開発者やデータベースにアクセスするために直接にスプライスSQLが得られ、その上のクエリの複雑な条件、サーバーのページングと解決しませんが。だから我々は、より使いやすいデータベースにアクセスする方法を望んでいました。

第二に、ライブラリの設計

データベースの操作は、インタラクティブなデータ転送が+コマンドで、データベースとの1つの相互作用をしていると見ることができ、我々は、データベースへの各アクセスを記述するために簡単なコードを使用しようとします。それはmysqljsデータベース操作をカプセル化することが可能で、データベースにアクセスするためのAPIを再設計。nodejsのAPIのMySQLデータベース・ツール・ライブラリへの強力かつスムーズなアクセスを提供し、目標は、データベース・ロジックは、コードの行を完了するために使用することができますアクセスし、それが簡単にデータベースとエレガントにアクセスできるようにすることです。オープンソース住所:https://github.com/liuhuisheng/ali-mysql-client

1.初期設定

次のように初期化

const db = new DbClient({
  host     : '127.0.0.1',
  user     : 'root',
  password : 'secret',
  database : 'my_db'
});

2.クエリを構築

  • 2.1クエリの単一の値
// 查询单个值,比如下面例子返回的是数字51,满足条件的数据条数
var result = await db
  .select("count(1)")
  .from("page")
  .where("name", "测试", "like")
  .queryValue();
  • 2.2単一のクエリデータ
// 查询单条数据,返回的是 result = {id:12, name: '测试页面', ....}
const result = await db
  .select("*")
  .from("page")
  .where("id", 12) // id = 12
  .queryRow();
  • 2.3クエリを複数のデータ
// 查询多条数据 返回的是 ressult = [{...}, {...}];
const result = await db
  .select("*")
  .from("page")
  .where("name", "测试页面", 'like') // name like '%测试页面%'
  .queryList();
  • 2.4サーバ側のページングクエリ
// 查询多条数据(服务端分页) 返回的是 ressult = {total: 100, rows:[{...}, {...}]};
const result = await db
  .select("*")
  .from("page")
  .where("id", 100, "lt") // id < 100
  .queryListWithPaging(3, 20); //每页 20 条,取第 3 页
  • クエリに関連した250以上のテーブル
// 多表关联查询
var result = await db
  .select("a.page_id, a.saga_key")
  .from("page_edit_content as a")
  .join("left join page as b on b.id = a.page_id")
  .where("b.id", 172)
  .queryList();
  • 外部結合クエリの様々なマルチテーブルを支持することに加えて2.6は、もちろん、他の複雑なクエリを有するサポートGROUPBY ORDERBY
const result = await db
  .select("a1 as a, b1 as b, count(c) as count")
  .from("table")
  .where("date", db.literals.now, "lt") // date < now()
  .where("creator", "huisheng.lhs")  // creator = 'huisheng.lhs"
  .groupby("a1, b1")
  .having("count(category) > 10")
  .orderby("id desc")
  .queryListWithPaging(2); //默认每页20条,取第2页

3.挿入構造

const task = {
  action: "testA",
  description: "desc1",
  state: "123",
  result: "result1"
};

// 插入一条数据
const result = await db
  .insert("task", task)
  .execute();

// 也支持直接写字段,支持增加字段
const result = await db
  .insert("task")
  .column("action", "test")
  .column("create_time", db.literals.now)
  .execute();

// 插入多条数据
const tasks = [ task1, taks2, task3 ];
const result = await db
  .insert("task", tasks)
  .execute();

// 支持增加或覆盖字段
const result = await db
  .insert("task", tasks)
  .column('create_time', db.literals.now)  // 循环赋值给每一行数据
  .column('create_user', 'huisheng.lhs')
  .execute();

4.アップデートの設定

const task = {
  action: "testA",
  description: "desc1",
  state: "123",
  result: "updateResult"
};

//更新数据
const result = await db
  .update("task", task)
  .where("id", 1)
  .execute();

//更新数据,支持增加字段
const result = await db
  .update("task")
  .column("action", "test-id22")
  .column("create_time", db.literals.now)
  .where('id', 2)
  .execute();

5.建設を削除

//删除id为1的数据
const result = await db
  .delete("task")
  .where("id", 1)
  .execute();

6.トランザクション制御

const trans = await db.useTransaction();

try {
  // 数据库操作
  // await trans.insert(...)
  // await trans.update(...)
  await trans.commit();
} catch (e) {
  await trans.rollback();
}

クエリデザインの7複雑な条件

7.1クエリのすべてのパラメータの説明

// 查询条件所有参数
const result = await db
  .where(field, value, operator, ignore, join) // 支持的所有参数
  .where({field, value, operator, ignore, join}) //支持对象参数
  .queryList();
  
// 复杂查询条件
const result = await db
  .select("*")
  .from("page")
  .where("id", 100, "gt") // id > 100
  .where("tags", "test", "like") //name like '%test%'
  .where("tech", tech, "eq", "ifHave") // tech='tech_value' 当 tech 为空时,不做为查询条件
  .where("tags", tags, "findinset", "ifHave", "or")
  .queryList();
  • フィールドのフィールド名
  • 値で渡された値
  • 演算子operator、デフォルトequal4
  • それはfalseを返したときの状態を無視するかどうかに追加、条件は無視されます
  • (とや)接続シンボルに参加し、デフォルトは

定義7.2オペレータのオペレーティングロジック

このパラメータは、よく理解され、デフォルト値が等しい、または定義されたロジックに一致させることができる文字列を渡し、受信文字列関数によってサポート

const result = await db
  .select("*")
  .from("page");
  .where("id", 100, "lt")  // id < 100
  .where("group_code", "dacu") // group_code = "dacu"
  .queryList();

私たちは、複雑な条件の容量を拡張するために使用されたクエリロジックパッケージステッチのためのオペレータが完了するためにオペレータによってカスタマイズすることができます理解することができます。この関数は次の形式があります。

const customOperator =  ({ field, value }) => {
  if (condition) {
    return {
      sql: '?? = ?',
      arg: [ field, value ],
    };
  } else {
    return {
      sql: '?? > ?',
      arg: [ field, value ],
    };
   }
};

// 可直接使用也可注册到全局
const config = db.config();
config.registerOperator("customOperator", customOperator);

7.3条件かどうかを無視することを追加します。

条件を無視XX満足しているクエリを説明するためのこの必要性は、もともと例えば、次のコードは共通で、入力値、クエリインターフェイスがあり、コードを簡素化するために設計された、クエリ条件が値を入力しないignoreは:

const query = db
  .select("*")
  .from("page");
  .where("id", 100, "lt");

if (name){
    query.where("name", name, 'like');
}

if (isNumber(source_id)){
    query.where('source_id', source_id)
}

const result = await query.queryList();

上記のコードは、の使用を無視するように簡略化することができます。

const result = await db
  .select("*")
  .from("page")
  .where("id", 100, "lt")
  .where("name", name, "like", "ifHave") //使用内置 ifHave,如果name为非空值时才加为条件
  .where("source_id", tech, "eq", "ifNumber") //使用内置 ifNumber
  .queryList();

次の関数の形で定義されたロジックに一致させることができる文字列を渡し、受信文字列またはサポート機能を渡します。

const customIgnore = ({field, value}) => {
    if (...){
        return false;
    }
    
    return true;
};

//也可以注册到全局使用
const config = db.config();
config.registerIgnore("customIgnore", customIgnore);

7.4プライオリティサポート問い合わせ

// where a = 1 and (b = 1 or c < 1) and d = 1
const result = await db.select('*')
  .from('table')
  .where('a', 1)
  .where([
    {field: 'b', value: '1', operator:'eq'},
    {field: 'c', value: '1', operator:'lt', join: 'or'},
  ])
  .where('d', 1)
  .queryList();

実際の場面で複雑なクエリの例7.5

// 复杂查询,真实场景示例,项目中拓展了keyword、setinset等operator及ignore
const result = await app.db
  .select('a.*, b.id as fav_id, c.name as biz_name, d.group_name')
  .from('rocms_page as a')
  .join(`left join favorite as b on b.object_id = a.id and b.object_type = "rocms_page" and b.create_user = "${this.ctx.user.userid}"`)
  .join('left join rocms_biz as c on c.biz = a.biz')
  .join('left join rocms_biz_group as d on d.biz = a.biz and d.group_code = a.biz_group')
  // 关键字模糊查询
  .where('a.name,a.biz,a.biz_group,a.support_clients,a.owner,a.status', query.keywords, 'keywords', 'ifHasValueNotNumber') // 关键字在这些字段中模糊查询
  .where('a.id', query.keywords, 'eq', 'ifNumber') // 关键字中输入了数字时当作id查询
  // 精确查询
  .where('a.id', query.id, 'eq', 'ifHave')
  .where('a.name', query.name, 'like', 'ifHave')
  .where('a.biz', query.biz, 'eq', 'ifHave')
  .where('a.biz_group', query.biz_group, 'eq', 'ifHave')
  .where('a.support_clients', query.support_clients, 'setinset', 'ifHave')
  .where('a.status', query.status, 'insetfind', 'ifHave')
  .where('a.owner', query.owner, 'eq', 'ifHave')
  .where('a.offline_time', query.owner, 'eq', 'ifHave')
  // TAB类型 我的页面own、我的收藏fav、所有页面all
  .where('a.owner', this.ctx.user.userid, 'eq', () => query.queryType === 'own')
  .where('b.id', 0, 'isnotnull', () => query.queryType === 'fav')
  // 分页查询
  .orderby('a.update_time desc, a.id desc')
  .queryListWithPaging(query.pageIndex, query.pageSize);

4.カスタム設定

const config = db.config();

// 自定义operator
config.registerOperator('ne', ({ field, value }) => {
  return { sql: '?? <> ?', arg: [ field, value ] };
});

// 自定义ignore
config.registerIgnore('ifNumber', ({ value }) => {
  return !isNaN(Number(value));
});

// 监听事件 执行前
config.onBeforeExecute(function({ sql }) {
  console.log(sql);
});

// 监听事件 执行后
config.onAfterExecute(function({ sql, result }) {
  console.log(result);
});

// 监听事件 执行出错
config.onExecuteError(function({ sql, error }) {
  console.log(error);
});

組み込みの演算子と無視

  • 内蔵のデフォルトの演算子
    • EQ(等しいです)
    • NE(等しくありません)
    • 中(中)
    • GT(より大きい)
    • GE(以上)
    • LT(未満)
    • ル(以下)
    • ISNULL(nullです)
    • isnotnull(nullではありません)
    • (のような)のような
    • startwith(で始まります)
    • ENDWITH(と終わり)
    • (間)
    • findinset(FIND_IN_SET(値、フィールド))
    • insetfind(FIND_IN_SET(フィールド、値))
    • SQL(カスタムSQL)
    • キーワード(キーワードクエリ)
  • 内蔵のデフォルト無視
    • ifHave(値を条件に追加された場合)
    • (値を条件に追加された場合)ますifNumber

第三に、例を使用して

それは卵-mysqlのeggjsで一緒に使用することができると、直接卵MySQLやアリ-RDSオブジェクトへのサポートは、接続プールを作成し、重複を避けるために、初期化されます。

// this.app.mysql 为egg-mysql对象
const db = new DbClient(this.app.mysql)

第四に、オープンソースプロジェクト

プロジェクトは当初、GitHubの、アリ- MySQLのクライアントにオープンソースに依存しているために、ネットワーク内の最近の統合に加えて、自分のプロジェクトの中に含むだけでネットワークを、リリースされました:https://github.com/liuhuisheng/ali-mysql-client

ライブラリは、コードの行を完了するために使用することができ、それが簡単にデータベースとエレガントにアクセスするために作るの目標は、データベース・ロジックにアクセスすることで、nodejs mysqlデータベースAPIにパワフルでスムーズなアクセスを提供するように設計されています。あなたはいつでも私にフィードバックを与えることができます任意のコメントや提案を歓迎します。

おすすめ

転載: www.cnblogs.com/xqin/p/11223813.html