ホームページ > テクノロジー周辺機器 > IT業界 > Elixir' s cecto querying dsl:beyond the basics

Elixir' s cecto querying dsl:beyond the basics

Lisa Kudrow
リリース: 2025-02-18 10:53:09
オリジナル
933 人が閲覧しました

Elixir' s cecto querying dsl:beyond the basics

Elixir' s cecto querying dsl:beyond the basics この記事は、ElixirのECTO Querying DSL:The Basicsを理解することでカバーしたECTOの基礎に基づいています。クエリ構成、結合と関連付け、SQLフラグメントインジェクション、明示的なキャスト、ダイナミックフィールドアクセスなど、ECTOのより高度な機能を探索します。

もう一度、Elixirの基本的な知識とEctoの基本が想定されています。これについては、ElixirのEcto Libraryの紹介で取り上げられています。

キーテイクアウト

ectoは、モデル内のテーブル関係(結合と関連性)を処理する機能を提供します。 has_one/3、has_many/3、およびbelongs_to/3マクロを使用して定義された協会は、開発者がモデルの外部キーとして実装されたテーブル関係を処理できるようにします。
    クエリ構成
  • 3つの個別のクエリを作成し、それらを組み合わせてドライヤーとより再利用可能なコードを実現する方法を見てみましょう。
  • SQLバージョンは非常に反復的ですが、一方、ECTOバージョンは非常に乾燥しています。最初のクエリ(get_users_overview)は、基本的なユーザー情報を取得するための一般的なクエリです。 2番目のクエリ(search_by_username)は、検索しているユーザー名に従ってユーザー名をフィルタリングすることにより、最初のクエリを構築します。 3番目のクエリ(paginate_query)は、2番目のクエリから構築され、結果を制限し、特定のオフセットから取得します(ページネーションの基礎を提供するため)。
  • 上記の3つのクエリのすべてを一緒に使用して、特定のユーザーが検索されたときの検索結果を提供できることを想像するのは難しくありません。それぞれを他のクエリと併せて使用して、他のアプリケーションのニーズを実行することもできます。これらはすべて、コードベース全体でクエリの一部を不必要に繰り返すことなく、

    参加して協会

    参加は、クエリするときはかなり基本的ですが、それでも今はそれらをカバーしているだけです。この理由は、Ectoだけで参加することについて学ぶことが役に立たないためです。同様に関連についても知る必要があります。これらについては学ぶのは難しくありませんが、これまでにカバーされている他のトピックほど些細なことではありません。 簡単に言えば、アソシエーションにより、開発者はモデル内のテーブル関係(外部キーとして実装)を処理できます。それらは、has_one/3およびhas_many/3マクロ(他のモデルを含むモデル用)を使用して各モデルのスキーマで定義され、belbings_to/3マクロ(他のモデルの範囲であるモデル - 外部キーを持つモデル) 。

    ectoingアプリケーションを見ると、ectoing.userモデルとectoing.messageモデルの間の関連性の1つの例を見ることができます。 ectoing.userで定義されているスキーマは、次の関連付けを定義しています:

    1人のユーザーが多くのメッセージ(ectoing.message)を持っていることがわかります。この協会を呼び出しています。メッセージ。 <span>SELECT id, username FROM users; </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%"; </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%" LIMIT 10, 0; </span>

    ここで、モデル、ectoing.messageはectoing.userモデルに属していると言っています。また、協会を以下と名付けました。デフォルトでは、ECTOは_IDをBENBSS_TO ASSOACITION名に追加し、それを外部キー名として使用します(ここでは、user_idになります)。このデフォルトの動作は、foreign_keyオプションを指定することにより、外部キー名を手動で指定することでオーバーライドできます。たとえば、

    ここで、参加を使用してユーザーとそのメッセージを取得する簡単なクエリを見てみましょう。
    offset <span>= 0
    </span>username <span>= <span>"%tp%"</span>
    </span>
    <span># Keywords query syntax
    </span>get_users_overview <span>= from u in Ectoing.User,
    </span>  <span>select: [u.id, u.username]
    </span>
    search_by_username <span>= from u in get_users_overview,
    </span>  <span>where: like(u.username, ^username)
    </span>
    paginate_query <span>= from search_by_username,
    </span>  <span>limit: 10,
    </span>  <span>offset: ^offset
    </span>
    <span># Macro syntax
    </span>get_users_overview <span>= (Ectoing.User
    </span><span>|> select([u], [u.id, u.username]))
    </span>
    search_by_username <span>= (get_users_overview
    </span><span>|> where([u], like(u.username, ^username)))
    </span>
    paginate_query <span>= (search_by_username
    </span><span>|> limit(10)
    </span><span>|> offset(^offset))
    </span>
    Ectoing<span>.Repo.all paginate_query
    </span>
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー

    返された値:
    has_many <span>:messages, Ectoing.Message
    </span>
    ログイン後にコピー

    注目すべきことに、メッセージ協会を含む多くのアンロードされた関連付けがあります。この関連付けの読み込みは、クエリの結果セットから、またはクエリ自体からの2つの方法のいずれかで実行できます。結果セットからのロード関連は、repo.preload関数を使用して実行できます:
    belongs_to <span>:user, Ectoing.User
    </span>
    ログイン後にコピー
    <span># Ectoing.Message
    </span>belongs_to <span>:user, Ectoing.User, foreign_key: some_other_fk_name
    </span>
    ログイン後にコピー
    クエリ内からのロードアソシエーションは、ASSOCとPreload関数の組み合わせを使用して実行できます。

    <span>SELECT * FROM users u INNER JOIN messages m ON u.id = m.user_id WHERE u.id = 4;
    </span>
    ログイン後にコピー
    次に、結果に関連付けられているメッセージがロードされています:

    <span># Keywords query syntax
    </span>query <span>= from u in Ectoing.User,
    </span>  <span>join: m in Ectoing.Message, on: u.id == m.user_id,
    </span>  <span>where: u.id == 4
    </span>
    <span># Macro syntax
    </span>query <span>= (Ectoing.User
    </span><span>|> join(:inner, [u], m in Ectoing.Message, u.id == m.user_id)
    </span><span>|> where([u], u.id == 4))
    </span>
    Ectoing<span>.Repo.all query
    </span>
    ログイン後にコピー
    協会は、私たちの主要なキーと外部のキー列に暗黙的に参加するため、句を指定する必要はありません。上記から、協会のプリロードに関しては、ゆっくりとロードされていないこともわかります。協会は、必要な場合は明示的にロードする必要があります この記事は、ECTOのDSLのクエリに特に焦点を当てているため、ここでの関連付けの挿入、更新、削除をカバーすることはありません。これの詳細については、Ecto AssociationsやEmbedsを使用してブログ投稿をご覧ください。

    SQLフラグメントインジェクション

    ユーザー名フィールドでケースに敏感な検索を実行しましょう。

    (上記にはMySQL固有のSQLが含まれています。別のデータベースを使用している場合、これは機能しません。
    <span>SELECT id, username FROM users;
    </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%";
    </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%" LIMIT 10, 0;
    </span>
    ログイン後にコピー
    ログイン後にコピー
    Fragment/1関数は、SQLコードを最初のパラメーターとして注入したい文字列として取得します。列と値をSQLコードフラグメントにバインドできるようにします。これは、文字列内のプレースホルダー(疑問符として)を介して行われ、その後の引数はそれぞれ各プレースホルダーに縛られています。
    offset <span>= 0
    </span>username <span>= <span>"%tp%"</span>
    </span>
    <span># Keywords query syntax
    </span>get_users_overview <span>= from u in Ectoing.User,
    </span>  <span>select: [u.id, u.username]
    </span>
    search_by_username <span>= from u in get_users_overview,
    </span>  <span>where: like(u.username, ^username)
    </span>
    paginate_query <span>= from search_by_username,
    </span>  <span>limit: 10,
    </span>  <span>offset: ^offset
    </span>
    <span># Macro syntax
    </span>get_users_overview <span>= (Ectoing.User
    </span><span>|> select([u], [u.id, u.username]))
    </span>
    search_by_username <span>= (get_users_overview
    </span><span>|> where([u], like(u.username, ^username)))
    </span>
    paginate_query <span>= (search_by_username
    </span><span>|> limit(10)
    </span><span>|> offset(^offset))
    </span>
    Ectoing<span>.Repo.all paginate_query
    </span>
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    明示的なキャスト

    ^usernameなどのクエリフラグメントがある場合、u.usernameはfield:username、:string in the schemaとして定義されます。ユーザー名変数は、ectoによって文字列に自動的にキャストされます。 >

    ただし、Ectoが定義されたフィールドタイプに補間された表現をキャストすることを常に望んでいるとは限りません。また、Ectoは、式をキャストするタイプを推測することができません(通常、これはSQLコードの断片が関与している場合です)。どちらの場合も、Type/2関数を使用して、キャストする式とそれをキャストする型を指定できます。 これは、これがより興味深いシナリオだからです。 Ectoingアプリケーションでは、ecto.schema.timestamps Macroを使用して、各テーブルに2つの追加フィールドを追加しました:updated_atとinserted_at。マクロは、デフォルトでは、これらのフィールドのタイプを設定して、ecto.datetimeの種類を持つように設定します。さて、今月に何人のユーザーが登録したかを確認したい場合は、次のような簡単なクエリを使用できます。

    ただし、ecto.date structをecto.dateTime structにキャストできないため、これはecto.casterrorを提供します(補間ecto.date式をタイプecto.datetimeのフィールドと比較しているため)。この場合、ecto.datetime structを構築するか、ecto.dateTimeの代わりにecto.dateに式をキャストしたいことをectoに指定することができます。

    さて、Ectoはクエリを喜んで受け入れます。キャスト操作の後、補間されたecto.date式を基礎となる日付タイプに変換します。これにより、基礎となるデータベース(MySQL、この場合)が日付と日付の比較を処理できます。

    動的フィールドアクセス

    クエリを一緒に作成することから例に戻りましょう。ここでは、ユーザー名検索を実行しました。

    <span>SELECT id, username FROM users;
    </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%";
    </span><span>SELECT id, username FROM users WHERE username LIKE "%tp%" LIMIT 10, 0;
    </span>
    ログイン後にコピー
    ログイン後にコピー
    その後に来たページネーションクエリのように、このクエリも一般化することができ、特定のテーブルから任意のフィールドを検索できます。これは、ダイナミックフィールドアクセスを実行することで実行できます。

    フィールド/2関数は、フィールドを動的に指定する必要がある場合に使用されます。その最初の議論は、アクセスするフィールドの表であり、2番目の引数は、アトムとして指定されたフィールドの名前自体です。上記のような一般的なクエリを使用して、関数内でそれをカプセル化し、パラメーターを使用して、指定されたクエリで指定されたテーブルから特定のフィールドを検索できます。
    offset <span>= 0
    </span>username <span>= <span>"%tp%"</span>
    </span>
    <span># Keywords query syntax
    </span>get_users_overview <span>= from u in Ectoing.User,
    </span>  <span>select: [u.id, u.username]
    </span>
    search_by_username <span>= from u in get_users_overview,
    </span>  <span>where: like(u.username, ^username)
    </span>
    paginate_query <span>= from search_by_username,
    </span>  <span>limit: 10,
    </span>  <span>offset: ^offset
    </span>
    <span># Macro syntax
    </span>get_users_overview <span>= (Ectoing.User
    </span><span>|> select([u], [u.id, u.username]))
    </span>
    search_by_username <span>= (get_users_overview
    </span><span>|> where([u], like(u.username, ^username)))
    </span>
    paginate_query <span>= (search_by_username
    </span><span>|> limit(10)
    </span><span>|> offset(^offset))
    </span>
    Ectoing<span>.Repo.all paginate_query
    </span>
    ログイン後にコピー
    ログイン後にコピー
    ログイン後にコピー
    結論

    に関するよくある質問(FAQ) ElixirのECTOはDSLをクエリしているのは何ですか?それが重要なのはなぜですか?

    ELIXIRのECTOクエリDSL(ドメイン固有言語)は、データベースと対話するための強力なツールです。 SQLに近い構文でクエリを書き込む方法を提供しますが、コンパイル時間の安全性、Elixirコードとのより良い統合、抽象化とコードの再利用の可能性の追加の利点があります。開発者は、より読みやすく保守可能な方法で複雑なクエリを書くことができ、エラーの可能性を減らし、コードを理解して修正しやすくすることができるため、重要です。

    ectoは、has_many、has_one、およびbelunks_to macrosを使用して、テーブル間の関連性を定義する方法を提供します。これらの関連性により、関連するデータを便利で効率的な方法で照会することができます。たとえば、ユーザースキーマがあり、各ユーザーに多くの投稿がある場合、簡単なクエリを持つユーザーのすべての投稿を取得できます。 ?

    はい、Ectoは、結合、サブクリーリー、集約など、幅広いクエリ操作をサポートしています。結合キーワードを使用して、テーブルを結合し、キーワードからサブクエリを作成し、sum、avg、min、maxなどの機能を作成して集約を実行できます。これにより、Ectoは複雑な方法でデータを照会するための強力なツールになります。

    ECTOはトランザクションをどのように処理しますか?

    ectoは、単一のトランザクションで複数の操作を実行できるRepo.Transaction関数を提供します。操作が失敗した場合、トランザクション内で行われたすべての変更がロールバックされます。これにより、データの一貫性と整合性が保証されます。

    ectoは最初にPostgreSQLで動作するように設計されていましたが、MySQLやMySQLなどの他のデータベースもサポートしています。 sqlite。 ECTOリポジトリをセットアップするときにデータベースタイプを指定できます。

    ectoは移行をどのように処理しますか?

    ectoは、データベーステーブルを作成、変更、削除できる堅牢な移行システムを提供します。制御された可逆的な方法。ミックスタスクを使用して移行ファイルを生成し、ECTOのDSLを使用して移行ファイルの変更を定義できます。はい、ECTOは、データベースに挿入または更新される前にデータを検証できるChangeset関数を提供します。スキーマ内の検証ルールを定義し、Changeset関数を使用してこれらのルールをデータに適用できます。ECTOはデータベース接続をどのように処理しますか?接続。これにより、複数の同時クエリを効率的に処理し、アプリケーションが重い負荷でも応答性が高いことを保証できます。高レベルの抽象化されたクエリを書く方法は、ecto.adapters.sql.query関数を使用して、必要に応じて生のsqlクエリを実行することもできます。 Ectoは、事前定義されたスキーマなしで動的にクエリを構築できるようにするecto.query.api.dynamic関数を提供します。これは、ユーザー入力またはその他のランタイムデータに基づいてクエリを作成する必要がある場合に役立ちます。

以上がElixir&#x27; s cecto querying dsl:beyond the basicsの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート