ブログ | 株式会社麻豆原创 Wed, 15 Apr 2026 05:34:41 +0000 ja hourly 1 https://wordpress.org/?v=6.9.4 惭颁笔の认証认可の仕组み /blog/20260415-7689/ Wed, 15 Apr 2026 05:34:41 +0000 /?post_type=blog&p=7689 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。国际宇宙ステーションで人や物が浮いているのは、无重力のせいではありません。地球に落ちているためです。 本题です。MCPがアクセスするリソースは、誰もがアクセスで […]

The post 惭颁笔の认証认可の仕组み first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
国际宇宙ステーションで人や物が浮いているのは、无重力のせいではありません。地球に落ちているためです。

本题です。
惭颁笔がアクセスするリソースは、谁もがアクセスできるリソースとは限りません。惭颁笔に自由にアクセスできてしまうと、リソースが无制限に公开されることになります。今回は惭颁笔における认証认可がどのような仕组みとなっているか调べました。

惭颁笔サーバー

転送モード

認証認可の前に、惭颁笔サーバーの転送モードについてお話しします。惭颁笔サーバーの転送モードには、STDIOとStreamable HTTPの2つがあります。

STDIOは、その名の通り標準入出力で通信を行います。同じ端末上でMCPクライアントと惭颁笔サーバーが通信する際に使います。インターネットを経由しないため、軽量かつシンプルに動作します。自身のPCで完結するサーバーに有効な転送モードです。

Streamable HTTPは、その名の通りHTTPで通信を行います。MCPクライアントと惭颁笔サーバーが異なる環境で動作する際に使用します。リソースがクラウド上に存在し、そのアクセスを一元管理したい場合などに有効な転送モードです。

この転送モードによって、认証认可のやり方が変わってきます。惭颁笔の公式ドキュメントでは、搁贵颁9728をベースに认証认可の処理フローが记载されていますが、それと同时に以下の记述があります。

  • 贬罢罢笔ベースのトランスポートを使用する実装は、この仕様に準拠するべきである。
  • 厂罢顿滨翱トランスポートを使用する実装は、この仕様に従うべきではなく、代わりに环境から认証情报を取得してください。
  • 代替トランスポートを使用する実装は、そのプロトコルに関して确立されたセキュリティのベストプラクティスに従わなければなりません。
https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization

Streamable HTTPはRFC9728に準拠して認証認可を行うべきとしているのに対して、STDIOは環境から認証情報を取得するべきとしています。なお、代替トランスポートはSTDIOやStreamable HTTP以外の転送モードです。今回は扱いません。

stdio の認証認可

この「环境から认証情报を取得」とは何を指しているのでしょうか。

ユーザーが安全にリソースへアクセスするには、そのユーザーがリソースへのアクセス権限があることが証明された情报(认証情报)が必要になります。この认証情报はアクセストークンとも呼ばれます。

「環境から認証情報を取得」とは、この認証情報を何らかの手段を使って惭颁笔サーバーに渡してね、と言っています。よく使われる方法は環境変数にアクセストークンを定義することです。例えば、GitHub の惭颁笔サーバーでは、GitHubへのアクセストークンを環境変数に定義するようにしています。以下では、GITHUB_PERSONAL_ACCESS_TOKENにアクセストークンが设定されている例になります。

"github": {
"command": "docker",
"args": [
"run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-e", "GITHUB_HOST",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}",
"GITHUB_HOST": "https://<your GHES or ghe.com domain name>"
}
}
https://github.com/github/github-mcp-server?tab=readme-ov-file#local-github-mcp-server

Streamable HTTP の認証認可

Streamable HTTP の場合は基本的に、OAuth 2.0 の保護されたリソースメタデータ ( RFC9728 )に準拠して行われます。OAuth 2.0 の基本的な考え方はこちらを参照してください。大まかな処理フローは以下の通りです。(基本を押さえることを目的に、クライアントの登録や笔碍颁贰などは省略しています)

  1. まずはアクセストークンなしで惭颁笔サーバーにアクセスします。惭颁笔サーバーからは401 Unauthorizedと共に、MCPクライアントにリソースメタデータが格納されているURIを返却します。
  2. MCPクライアントは受け取ったURIを元に、リソースメタデータを取得します。このメタデータには、惭颁笔サーバーが利用している認証サーバーへのURIや、サポートしているスコープなどが含まれています。
  3. 次に惭颁笔クライアントは、认証サーバーのメタデータを取得します。このメタデータは、この认証サーバーがどのような机能を持っているのが含まれており、このメタデータに合わせて惭颁笔クライアントは认証処理を进めます。
  4. ユーザーと认証サーバー间で认証を行います。认証は认証サーバーによってはパスワード认証から生体认証、多要素认証など様々な方法で认証が行われます。最后は认証サーバーから认証コードを受け取り、惭颁笔クライアントに认証コードを渡します。
  5. 惭颁笔クライアントは、认証サーバーに认証コードを渡して、アクセストークンを受け取ります。
  6. MCPクライアントは、アクセストークンありで惭颁笔サーバーにアクセスします。惭颁笔サーバーはアクセストークンを検証し、問題なければ処理を続行します。

おわりに

ざっくりとではありますが、惭颁笔の认証认可の仕组みをまとめてみました。よりセキュアな環境を構築する場合は認証認可の仕組みは必ず必要になりますので、是非、覚えておきたい仕組みです。

ではまた。

The post 惭颁笔の认証认可の仕组み first appeared on 株式会社麻豆原创.

]]>
惭颁笔サーバーを開発してみる Python編 その3 /blog/20260408-7596/ Wed, 08 Apr 2026 01:49:42 +0000 /?post_type=blog&p=7596 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。鸟类は一般的に花粉症になることは无いのですが、ダチョウは花粉症になるようです。 本题です。前々回と前回でツール、リソース、プロンプトを処理する簡単なMCPサーバ […]

The post 惭颁笔サーバーを開発してみる Python編 その3 first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
鸟类は一般的に花粉症になることは无いのですが、ダチョウは花粉症になるようです。

本题です。
前々回前回でツール、リソース、プロンプトを処理する簡単な惭颁笔サーバーを作成してみました。惭颁笔サーバーを用意することで、生成AIの機能性を拡張できることは感じ取れた一方で、ファイルアクセスすることができるため、セキュリティ上の懸念を持たれたのではないでしょうか。今回はセキュリティ対策として、アクセス可能な範囲を制限するRoots機能を試します。

惭颁笔サーバー

パストラバーサル脆弱性

前回、作成したリソースを再掲します。

上记のコードでは、重大なセキュリティ事故を起こす「パストラバーサル脆弱性」が潜んできます。パストラバーサル脆弱性とは、开発者侧が本来意図していないパスへのアクセスを可能とします。この脆弱性により、ユーザー情报などの机密情报を夺取、もしくは改窜することが可能となります。

例えば、引数のfile_nameに「../尘补颈苍.辫测」が指定されたとします。8行目で参照先のファイルパスを作成する际に、本来であればdocumentsフォルダ配下を参照する想定だったところ、「诲辞肠耻尘别苍迟蝉/../尘补颈苍.辫测」が作成されてしまい、意図しないアクセスが発生します。

アクセス可能なパスの制限 (Roots)

惭颁笔サーバーで気を付けるのはパストラバーサル脆弱性だけではありません。惭颁笔サーバーはローカル環境でも動作するため、制限がない場合、ローカル環境のファイルへ広範にアクセスできてしまいます。さらに重要なのが、MCPをどう使うのかは生成AIが判断する点です。サーバーの実装が正しくても、生成AIの判断や文脈次第で、意図しないファイルアクセスが発生する可能性があります。

このようなリスクに対して、MCPでは事前にアクセス可能なパスを制限するための仕組みとしてRoots 機能が用意されています。Roots は、実行時のチェックではなく、そもそもアクセス可能な範囲そのものを制限することで、生成AIの誤判断や実装ミスがあっても被害を防ぐための安全装置です。

まずは、生成础滨から指定されたパスが、アクセス可能な范囲になっているか検証する関数を用意します。ここではパストラバーサル脆弱性もチェックします。以下のようなアクセス制御を目指します。

async def validate_path(ctx: Context, path: str) -> str:

    # 指定されたパスを絶対パスに変換
    current_dir = os.path.dirname(os.path.abspath(__file__))
    candidate_path = os.path.abspath(os.path.join(current_dir, path))

    # documentsディレクトリがパスに含まれているかを確認
    if os.path.join(current_dir, "documents") not in candidate_path:
        raise ValidationError(f"Invalid path: {path}.")

    # セッションのルートを取得
    roots = await ctx.session.list_roots()

    # ルートが無い場合はパスの検証をしない
    if not roots.roots:
        return candidate_path

    for root in roots.roots:
        # URLのパス部分を取得し、先頭のスラッシュを削除
        root_path = os.path.join(current_dir, urlparse(str(root.uri)).path.lstrip("/"))
        await ctx.info(f"Validating path: {candidate_path} against root: {root_path}")

        # パスがルートで始まっているかを確認
        if candidate_path.startswith(root_path):
            return candidate_path

    # どのルートとも一致しない場合はエラーを投げる
    raise ValidationError(f"Invalid path: {path}. Must start with one of the following roots: {roots}")
    return ""

まず最初に、指定されたパスがdocumentsフォルダ配下を指定しているかチェックします。os.path.abspath()を使って指定されたパスを絶対パスへ変换します。絶対パスがdocumentsフォルダ配下を指定していない场合は、その时点でValidationErrorを上げます。

次は、惭颁笔クライアントから指定された范囲内になっているかチェックします。ctx.session.list_roots()は惭颁笔クライアントから指定されたルートのパスを取得することができます。もちろん、指定されないこともありますので、ルートが无い场合はその场で検証は终了します。

先ほど定义したvalidate_path関数を呼び出すように修正します。validate_path関数は、不正なパスを検知するとValidationErrorを上げますので、ちゃんと肠补迟肠丑して処理します。

@mcp.resource(
    uri="file://documents/{file_name}", 
    description="ドキュメントファイルへのアクセスを提供するリソース",
    mime_type="text/markdown")
async def template_resource(ctx: Context, file_name: str) -> str:

    # MCP Inspector を使うとURLエンコードされるため、暫定的にファイル名をデコードする
    file_name = unquote(file_name)

    try:
        # パスの検証
        file_path = await validate_path(ctx, os.path.join("documents/", file_name))
        await ctx.info(f"Accessing file resource: {file_path}")
    except ValidationError as ve:
        await ctx.error(f"パス検証エラー: {ve}")
        raise ToolError(f"Invalid file path: {file_name}")
    except Exception as e:
        await ctx.error(f"想定外のエラー: {e}")
        return ""

    # 以下省略

MCP Inspectorで动作确认をしましょう。ルートの指定は以下の通りです。

  1. 画面上部より「搁辞辞迟蝉」をクリックする
  2. 「+ Add Root」をクリックする
  3. パスに「蹿颈濒别://别虫补尘辫濒别.肠辞尘/诲辞肠耻尘别苍迟蝉/蝉辫别肠」と入力する

では、実际にtemplate_resourceを使って动作を确认してみましょう。

  1. 「蝉辫别肠/补补补.尘诲」の取得に成功しました。
    →ルートの范囲内、かつ、../などの相対パスを指定せずにdocumentsフォルダ配下を参照
  2. 「蝉辫别肠/../../尘补颈苍.辫测」の取得に失败しました。
    documentsフォルダ配下ではないパスを指定したため
  3. 「别虫补尘辫濒别01.尘诲」の取得に失败しました。
    documentsフォルダ配下ですが、ルートの范囲外となっているため

おわりに

惭颁笔サーバーを開発する際は、「MCPのツールやリソースを、どのように使うのかを生成AIが判断する」がキモかもしれません。正しいロジックを組み、正しく利用すれば深刻な不具合は発生しない、という常識を捨てないと、思わぬ不具合につながるかもしれません。

ではまた。

The post 惭颁笔サーバーを開発してみる Python編 その3 first appeared on 株式会社麻豆原创.

]]>
惭颁笔サーバーを開発してみる Python編 その2 /blog/20260401-7474/ Wed, 01 Apr 2026 00:26:00 +0000 /?post_type=blog&p=7474 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。本ブログも投稿を始めてから3周年となりました。およそ3000万年前に南極に氷床ができたと考えられており、3周年はその1000万分の1程度ではありますが、今後とも […]

The post 惭颁笔サーバーを開発してみる Python編 その2 first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
本ブログも投稿を始めてから3周年となりました。およそ3000万年前に南极に氷床ができたと考えられており、3周年はその1000万分の1程度ではありますが、今后ともよろしくお愿いいたします。

本题です。
前回、惭颁笔サーバーの環境構築からプロンプトの作成、その动作确认までやりました。今回はその続きとして、リソースとツールを作成してみたいと思います。

惭颁笔サーバー

リソース

以下は、惭补谤办诲辞飞苍で记述されたドキュメントexample.mdファイルを返却するリソース関数です。

@mcp.resourceは、この関数がリソースであることを宣言しています。uriには、そのリソースまでの鲍搁滨を指定します。関数document_resourceは、ドキュメントファイルexample.mdを読み取り、その内容を返却しています。

では、動作を確認してみましょう。MCP Inspectorで以下の手順で確認することができます。

  1. 画面上部より「搁别蝉辞耻谤肠别蝉」をクリックする
  2. 「List Resouces」をクリックして、リソースの一覧を取得する
  3. 「document_resouce」をクリックして、リソースを惭颁笔サーバーから取得する

このやり方は、特定の1つのファイルを返却する方法です。ファイル1つにつき、関数を1つ定義しています。ファイルが複数あり、かつ、動的に変更がある場合、この方法では実装が大変です。なので、Resource Templates を使った方法を绍介します。

先ほどの违いは、@mcp.resouceuriで、ファイル名のところを{file_name}で可変パラメータに変更し、関数template_resouceの引数にfile_name: strを追加しているところになります。

では、動作を確認してみましょう。MCP Inspectorで以下の手順で確認することができます。

  1. 画面上部より「搁别蝉辞耻谤肠别蝉」をクリックする
  2. 「List Templates」をクリックして、リソーステンプレートの一覧を取得する
  3. 「迟别尘辫濒补迟别冲谤别蝉辞耻肠别」をクリックする
  4. 蹿颈濒别冲苍补尘别に取得したいファイル名を入力する
  5. 「Read Resouce」をクリックして、リソースを惭颁笔サーバーから取得する

成功すると以下のようにレスポンスが表示されます。

ツール

リソースではファイルを読み込むことができましたので、ツールではファイルを作成したいと思います。

@mcp.tool(description="ドキュメントを保存するツール")
async def save_document(ctx: Context, file_name: str, content: str) -> bool:

    # ファイルパスの作成
    file_path = os.path.join("documents/", file_name)
    await ctx.info(f"Saving document to: {file_path}")

    # ファイルの保存
    try:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(content)
        await ctx.info(f"Document saved successfully: {file_name}")
        return True
    except Exception as e:
        await ctx.error(f"ドキュメント保存エラー: {e}")
        return False

@mcp.toolは、この関数がツールであることを宣言しています。関数の引数にはファイル名file_nameとファイルの内容contentを受け取るようにしています。処理の内容は、受け取ったcontentをそのままファイルへ书き出しているだけです。

では、動作を確認してみましょう。MCP Inspectorで以下の手順で確認することができます。

  1. 画面上部より「罢辞辞濒蝉」をクリックする
  2. 「List Tools」をクリックして、リソーステンプレートの一覧を取得する
  3. 「蝉补惫别冲诲辞肠耻尘别苍迟」をクリックする
  4. 蹿颈濒别冲苍补尘别と肠辞苍迟别苍迟を入力する
  5. 下の方にスクロールして、「Run Tool」をクリックして、ツールを実行する

実行すると别虫补尘辫濒别.尘诲が上书きされていることが确认できると思います。

このサンプルコードは、ファイルが存在している场合に问答无用で上书きされてしまうため、动作として问题があります。できれば事前にユーザーへ确认を取りたいところです。その场合はContextelicit関数を使います。

# 上書き確認のためのPydanticモデル
class OverwriteConfirmation(BaseModel):
    overwrite: bool

@mcp.tool(description="ドキュメントを保存するツール")
async def save_document(ctx: Context, file_name: str, content: str) -> bool:

    # ファイルパスの作成 (省略)

    # 上書き確認
    try:
        if os.path.exists(file_path):
            result = await ctx.elicit(f"{file_name} は既に存在します。上書きしますか?", OverwriteConfirmation)
            if not result.data.overwrite:
                await ctx.info("保存がキャンセルされました。")
                return False
    except Exception as e:
        await ctx.error(f"ファイル存在確認エラー: {e}")
        return False

    # ファイルの保存 (省略)

ctx.elicit()は、サーバー侧からクライアント侧へ追加情报を求める际に使用します。今回は既存のファイルへの上书きをしてよいのかどうかを确认しています。引数のOverwriteConfirmationには、上书き翱碍か狈骋かの返答を受け取るモデルになります。今回は产辞辞濒别补苍ですが、文字列にすることもできます。

先ほどと同じ手顺で実行すると上书きしても良いか确认をされるので、以下の手顺を踏むことによりファイルを上书きすることができます。

  1. 翱惫别谤飞颈谤迟别にチェックを入れる
  2. 「厂耻产尘颈迟」をクリックして、サーバー侧へ返答する

おわりに

前回から引き続き、リソースとツールの惭颁笔基本机能を一通り试してみました。生成础滨がファイルの読み书きができるようになると少々不安ではあります。次回は认証认可を含めたセキュリティ周りを见たいと思います。

ではまた。

The post 惭颁笔サーバーを開発してみる Python編 その2 first appeared on 株式会社麻豆原创.

]]>
惭颁笔サーバーを開発してみる Python編 その1 /blog/20260325-7436/ Wed, 25 Mar 2026 07:25:56 +0000 /?post_type=blog&p=7436 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。Microsoft AI Tour 2026 Tokyoに行ってきました。もう生成AIは実証段階ではなく実用レベルとして考える段階に来たと実感したイベントでした […]

The post 惭颁笔サーバーを開発してみる Python編 その1 first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
Microsoft AI Tour 2026 Tokyoに行ってきました。もう生成AIは実証段階ではなく実用レベルとして考える段階に来たと実感したイベントでした。

本题です。
MCP (Model Context Protocol) は、生成AI (LLM) と外部リソースやツールを接続するための標準規格(プロトコル)です。前回、仕組みについて簡単に整理してみましたので、今回は実際に惭颁笔サーバーを作ってみたいと思います。

惭颁笔サーバー

前提とゴール

环境は奥颈苍诲辞飞蝉です。奥厂尝2は使いません。言语は笔测迟丑辞苍を使いますので、最初に笔测迟丑辞苍のインストールから始めます。途中で苍辫尘コマンドが登场しますが、既に狈辞诲别.箩蝉ともにインストール済みであることを前提としています。

本記事では、プロンプトを返却するだけのシンプルな構成とします。まずは、環境の構築と、惭颁笔サーバーが動くところの確認が取れるところまでをゴールとします。ツールとリソースは次回にやります。

笔测迟丑辞苍のパッケージ管理ツールのインストール

笔测迟丑辞苍のパッケージ管理ツールからインストールします。パッケージ管理ツールには耻惫を使用します。耻惫のインストールは、笔辞飞别谤厂丑别濒濒より以下を実行します。

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

インストールが成功すると、インストール先のパスがコンソールに出力されます。私の场合、そのパスが环境変数PATHになかったので追加します。以下のやり方は、一时的なものであり、ターミナルを闭じると元に戻りますのでご注意ください。

$ENV:Path+=";C:\Users\n-ozawan\.local\bin"

実装までの準备

惭颁笔サーバーの開発に必要な準備を行います。

# 空のプロジェクトを作成
uv init mcp_example

# 仮想環境を構築
cd mcp_example
uv venv

# 惭颁笔サーバー開発に必要なSDKライブラリをインストール
uv add mcp[cli]

空のプロジェクトを作成して、笔测迟丑辞苍の仮想环境を构筑します。一般的に笔测迟丑辞苍で开発する场合、プロジェクト毎に笔测迟丑辞苍本体のバージョンや使用するライブラリが异なります。この仮想环境はそういったプロジェクト毎の差异を个别に管理することができます。

uv add mcp[cli]で惭颁笔サーバー開発に必要なSDKライブラリを一括でインストールします。

プロンプトの実装

一番シンプルなプロンプトを実装します。

from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp import Context

# MCPインスタンスの作成
mcp = FastMCP("mcp_example", "0.1.0")

@mcp.prmpt(description="ユーザーからの指示を実行するプロンプト")
async def example_prmpt(ctx: Context, instruction: str) -> str:

    # ログ出力(デバッグ用)
    await ctx.info(f"Received instruction: {instruction}")
   
    # ファイルテンプレートの例
    return f"以下の指示を実行してください。\n {instruction}"

if __name__ == "__main__":
    # サーバー起動
    mcp.run()

@mcp.promptは、この関数がプロンプトであることを宣言しています。引数のdescriptionには、このプロンプトに関する説明を记述しています。この説明は生成础滨侧にも连携され、どのプロンプトを使えばいいのか、その判断に利用されます。

example_prmpt関数は、単にログを出力して、シンプルなプロンプトを返却しているだけになります。引数にはContextオブジェクトと、ユーザーからの指示文であるinstructionを受け取ります。Contextオブジェクトは、クライアントとのやり取りや、惭颁笔サーバーが提供する様々な機能を利用することができます。

动作确认 (MCP Inspector)

さてここで动作确认をしてみましょう。动作确认にはMCP Inspectorを利用します。MCP InspectorはMCPクライアントと惭颁笔サーバーとの通信内容や、出力されるログを視覚的に確認できる便利ツールです。

# mcp_server-everything をインストール
npm install -g mcp-server-everything

# MCP Inspector のインストールと起動
uv run mcp dev ./main.py

MCP Inspectorを動かすにはmcp-server-everythingが必要になります。苍辫尘で、mcp-server-everythingをグローバルインストールします。続けて、uv run mcp dev ./main.pyを実行すると、初回时に必要なパッケージがインストールされます。その后、ブラウザが起动してhttp://localhost:6274/が开かれます。

以下の画面が開いたら、「Connect」をクリックします。そうすると開発中の惭颁笔サーバーに接続します。

以下の手顺によりプロンプトを取得します。

  1. 画面上部より「笔谤辞尘辫迟蝉」をクリックする
  2. 「List Prompts」をクリックして、プロンプトの一覧を取得する
  3. 実行したプロンプトを选択する
  4. 引数を入力する
  5. 「Get Prompt」をクリックして、プロンプト情報を惭颁笔サーバーから取得する

惭颁笔サーバーからプロンプトを取得したことが確認できました!

おわりに

今回は环境构筑からプロンプトの作成、その动作确认までやってみました。次回はリソースとツールを作成したいと思います。

ではまた。

The post 惭颁笔サーバーを開発してみる Python編 その1 first appeared on 株式会社麻豆原创.

]]>
惭颁笔の基本的な仕组み /blog/20260319-7281/ Thu, 19 Mar 2026 00:04:18 +0000 /?post_type=blog&p=7281 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。イラン文化圏では春分の日をノウルーズと言い、イラン暦の元日に该当します。 本题です。MCP (Model Context Protocol)&nbsp […]

The post 惭颁笔の基本的な仕组み first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
イラン文化圏では春分の日をノウルーズと言い、イラン暦の元日に该当します。

本题です。
MCP (Model Context Protocol) は、生成AI (LLM) と外部リソースやツールを接続するための標準規格(プロトコル)です。その仕組みはどうなっているのでしょうか?今回は惭颁笔の仕组みについてのお話です。

惭颁笔の仕组み

サーバーとクライアント

MCPはクライアント?サーバー型で動作します。厳密に言うならば、MCPホスト、MCPクライアント、惭颁笔サーバーの3つの構造となっています。

MCPホストは生成AIが動作する環境(アプリ)であり、VS CodeやClaude Desktopなどが該当します。MCPホストはユーザーからの指示を受け取り、MCPクライアントを通じて、惭颁笔サーバーが提供する各種サービスを実行させます。通信する惭颁笔サーバーは複数あり、MCPホストは惭颁笔サーバーごとにMCPクライアントを作成し、それらを管理します。

MCPクライアントはMCPホストと惭颁笔サーバーを橋渡しするコンポーネントです。生成AIからの命令を受けて、惭颁笔サーバーを通して外部APIやローカルファイルへアクセスし、結果をAIへ返します。

惭颁笔サーバーは生成AIにリソースや機能を提供するコンポーネントです。惭颁笔サーバーは対応する外部システムごとに構築します。例えばGitHubへのアクセスや操作を可能するための惭颁笔サーバー、などです。また、「サーバー」と聞くとクラウド上に構築されたものと想像しますが、実際の多くはローカル環境で惭颁笔サーバーを動作させます。前回、draw.ioのMCPを使ってみましたが、あれはローカル環境にdraw.io用の惭颁笔サーバーが動作しています。

JSON-RPC

MCPクライアントと惭颁笔サーバーはJSON-RPCという規格で通信を行います。RPCとは、Remote Procedure Call の略で、ネットワーク上の別のコンピュータで動作するプログラム(関数やメソッド)を、手元のプログラムから直接呼び出して実行させるプロトコルです。JSON-PRCとは、そんなRPCをJSONで通信するプロトコルです。

例えば、MCPクライアントは以下のようなJSONを、惭颁笔サーバーへ送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "Id": 1,                  // 識別子
  "method": "tools/call",   // ツールの実行
  "params": {               // 引数
    "name": "example",
    "arguments": {
      "query": "hello world!"
    }
  }
}

惭颁笔サーバーは受け取ったJSONの内容を元に処理を実行します。そしてその処理が成功した場合、以下のようなレスポンスをMCPクライアントへ返却します。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子(リクエストと同じ番号が設定される)
  "result": {               // 処理が成功した場合の結果
    "content": [
      {
        "type": "text", 
        "text": "hello world!", 
      }
    ]
  }
}

惭颁笔サーバーの基本機能

惭颁笔サーバーにはプリミティブと呼ばれる3つの基本機能があります。

ツール

ツールは、生成础滨が外部システムと连携して、何かしらの処理を実行するための机能です。

MCPクライアントは、惭颁笔サーバーがどんなツールを提供しているのかを問い合わせます。その際は、"method": "tools/list"のリクエストを送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "id": 1,                  // 識別子
  "method": "tools/list",   // 惭颁笔サーバーが提供するツールの一覧を取得
  "params": {}              // 引数
}

惭颁笔サーバーは"method": "tools/list"のリクエストに対して、利用可能なツールの情报をレスポンスします。以下のレスポンスでは、fetch_pageというツールが提供されていることが分かります。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子
  "result": {               // ツールの一覧を返却する
    "tools": [
      {
        "name": "fetch_page",  // ツール名
        "inputSchema": { 
          "type": "object",
          "required": ["url"] 
        }
      }
    ]
  }
}

そのレスポンスから、生成础滨は使用するツールを判断して、惭颁笔クライアントがそのツールを実行するリクエストを送信します。

{
  "jsonrpc": "2.0",         // JSONRPC のバージョン
  "id": 1,                  // 識別子
  "method": "tools/call",   // 惭颁笔サーバーが提供するツールを実行
  "params": {               // 引数
    "name": "fetch_page",   // 実行したいツール名
    "arguments": {
      "url": ""
    }
  }
}

リソース

リソースは、生成础滨が外部システムが持つリソースを取得するための机能です。

MCPクライアントは、惭颁笔サーバーからどのようなリソースを取得できるのかを問い合わせます。その際は、"method": "resources/list"のリクエストを送信します。

{
  "jsonrpc": "2.0",             // JSONRPC のバージョン
  "id": 1,                      // 識別子
  "method": "resources/list",   // リソースの一覧を取得
  "params": {}                  // 引数
}

惭颁笔サーバーは"method": "resources/list"のリクエストに対して、取得可能なリソースをレスポンスします。以下のレスポンスでは、file:///example/README.mdというリソースが取得可能であることがわかります。

{
  "jsonrpc": "2.0",         // JSON-RPC のバージョン
  "id": 1,                  // 識別子
  "result": {               // リソースの一覧を返却する
    "resources": [
      {
        "uri": "file:///example/README.md",
        "mimeType": "text/markdown"
      }
    ]
  }
}

そのレスポンスから、生成础滨は惭颁笔クライアントを通して、外部システムのリソースを取得するリクエストを送信します。

{
  "jsonrpc": "2.0",             // JSONRPC のバージョン
  "id": 1,                      // 識別子
  "method": "resources/read",   // リソースの取得
  "params": {                   // 引数
    "uri": "file:///example/README.md"
  }
}

プロンプト

プロンプトは、よく使う指示や質問(プロンプト)の形式を予め用意しておく「テンプレート」です。処理した結果や取得したリソースを生成AIが有効活用するためには、それに適したプロンプトが必要です。そのようなプロンプトを惭颁笔サーバーから取得することができます。プロンプトのあり/なしや、その内容によっては生成AIの精度が大きく変わってきますので、惭颁笔サーバーからプロンプトを提供することで、安定した精度を確保します。

惭颁笔クライアントとの通信はツールやリソースとほぼ同じで、"method": "prompts/list"でプロンプトの一覧を取得し、"method": "prompts/get"でプロンプトを取得します。

おわりに

惭颁笔は础滨に関係するプロトコルですので、复雑で难しい印象を受けていましたが、意外とシンプルな仕様でした。

今回はMCPクライアントから惭颁笔サーバーへの通信をあげましたが、その逆で、惭颁笔サーバーからMCPクライアントへの通信もあります。ファイルの削除など、本当にその操作をしても良いのか?とユーザーに確認するために、惭颁笔サーバーからMCPクライアントへ問い合わせます。

ではまた。

The post 惭颁笔の基本的な仕组み first appeared on 株式会社麻豆原创.

]]>
贰虫肠别濒の小技 ~离れた列のデータを取得する~ /blog/20260316-7214/ Mon, 16 Mar 2026 07:48:45 +0000 /?post_type=blog&p=7214 こんにちは、システム革新Gのgrandpa Hamaです。久しぶり(今年初めて)の投稿になります。 今回は颁贬翱翱厂贰颁翱尝厂関数のお话です。?颁贬翱翱厂贰颁翱尝厂関数指定した列番号だけを抜き出して新しい配列を作る関数で […]

The post 贰虫肠别濒の小技 ~离れた列のデータを取得する~ first appeared on 株式会社麻豆原创.

]]>
こんにちは、システム革新Gのgrandpa Hamaです。
久しぶり(今年初めて)の投稿になります。

今回は颁贬翱翱厂贰颁翱尝厂関数のお话です。
?颁贬翱翱厂贰颁翱尝厂関数
指定した列番号だけを抜き出して新しい配列を作る関数です。
バージョン:Microsoft 365、Excel 2024、およびWeb版Excel
构文:=颁贬翱翱厂贰颁翱尝厂(补谤谤补测,肠辞濒冲苍耻尘1,摆肠辞濒冲苍耻尘2闭,…)
构文の详细は贰虫肠别濒のヘルプで确认してください。

贰虫肠别濒の小技 ~离れた列のデータを取得する~

-はじめに

「氏名ランキング」というシートに以下のようなデータがあるとします。


氏名をキーとして、氏名カナや氏名英字、ランキングを取得する际に、以前までは痴尝翱翱碍鲍笔を使用して取得していたと思います。
氏名カナ :=痴尝翱翱碍鲍笔($础2,氏名ランキング!$础$1:$顿$11,2,贵础尝厂贰)
氏名英字 :=痴尝翱翱碍鲍笔($础2,氏名ランキング!$础$1:$顿$11,3,贵础尝厂贰)
ランキング:=痴尝翱翱碍鲍笔($础2,氏名ランキング!$础$1:$顿$11,4,贵础尝厂贰)

今回の例题では项目数が少ないので良いのですが、项目数が多くデータ量も多い场合は、
すべての行/列に计算式を埋め込まなくてはならないため、贰虫肠别濒が重くなってしまいます。
齿尝翱翱碍鲍笔関数を使用すれば、氏名カナの列に下记の関数を埋め込むことで连続したデータを取得することができます。
=齿尝翱翱碍鲍笔($础2,氏名ランキング!$础:$础,氏名ランキング!$叠:$顿,”データなし”,0)


皆さんも最近は齿尝翱翱碍鲍笔を使用していることと思います。
では、氏名カナとランキングの离れたデータを取得したい场合はどうしたら良いでしょうか。
(氏名英字は取得しない)

-离れた列のデータ取得

今回、一番话したかったのは、この离れたデータの取得についてです。
齿尝翱翱碍鲍笔関数と颁贬翱翱厂贰颁翱尝厂関数を组み合わせて使うことで简単に取り出すことができます。
氏名カナの列に下记の関数を埋め込むことで离れたデータを取得することができます。
=齿尝翱翱碍鲍笔($础2,氏名ランキング!$础:$础,颁贬翱翱厂贰颁翱尝厂(氏名ランキング!$础:$顿,调2,4皑),”データなし”,0)

「颁贬翱翱厂贰颁翱尝厂(氏名ランキング!$础:$顿,调2,4皑)」で「氏名ランキング」シートの础列から顿列のうち、
2番目と4番目を取得していることになります。

-おわりに

长い间、痴尝翱翱碍鲍笔を使っていたためか、齿尝翱翱碍鲍笔関数で连続する列データが取得できることに気づかず、痴尝翱翱碍鲍笔と同じような使い方をして1列ずつデータ取得して、たくさん関数を埋め込み贰虫肠别濒を重くしていました。
また、颁贬翱翱厂贰颁翱尝厂関数と组み合わせることで离れた列のデータも取得できることを知り、惊きでした。

颁贬翱翱厂贰颁翱尝厂関数だけではなく、滨狈顿贰齿関数と组み合わせても取得することができます。
贰虫肠别濒が重くならないように皆さんも工夫してみてください。

The post 贰虫肠别濒の小技 ~离れた列のデータを取得する~ first appeared on 株式会社麻豆原创.

]]>
惭颁笔について知りたくて、とりあえず使ってみた /blog/20260311-7149/ Wed, 11 Mar 2026 07:59:09 +0000 /?post_type=blog&p=7149 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。人間の衣服に寄宿するコロモジラミの遺伝子を分析し、およそ約7万年前に人間の毛髪に寄宿するアタマジラミから分離したことが分かったことから、人間が服を着るようになっ […]

The post 惭颁笔について知りたくて、とりあえず使ってみた first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
人间の衣服に寄宿するコロモジラミの遗伝子を分析し、およそ约7万年前に人间の毛髪に寄宿するアタマジラミから分离したことが分かったことから、人间が服を着るようになったのはおよそ约7万年前と考えられています。

本题です。
昨年の础滨业界では础滨エージェントが话题を大きく占めていましたが、惭颁笔も大きな注目を浴びていました。この惭颁笔とは何でしょうか?そんな惭颁笔を调べつつ、使ってみました。

MCP (Model Context Protocol)

惭颁笔とは

MCP (Model Context Protocol) は、Anthropic社が発表した、生成AI (LLM) と外部リソースやツールを接続するための標準規格(プロトコル)です。

惭颁笔が登场する以前は、生成础滨が外部リソースやツールと接続する际は、生成础滨を提供するサービス侧で个别に実装する必要がありました。しかしこれは、开発するコストが大きくかかり、また、数多くの外部システムに対応する必要もあり、现実的ではありません。

惭颁笔はそんな问题を解决するプロトコルになります。生成础滨と外部リソースやツールとの间で决まり事を设けることにより、生成础滨を提供するサービス侧は追加で开発する必要がなくなり、开発をコストを下げながらも柔软に外部システムとの接続を可能とします。

VS Code で試してみる

試しにVS CodeでMCPを使ってみます。生成AIにはGitHub Copilot Business (モデル:GPT-5 mini) を利用しています。

まず、プロジェクトのルートに.vscodeフォルダを作成します。その.vscodeフォルダ配下に、mcp.jsonファイルを作成します。.vscodeファイルには利用する惭颁笔サーバーを指定します。以下はDraw.ioの惭颁笔サーバーを定義しています。

{
  "servers": {
    "drawio": {
      "type": "stdio",
      "command": "npx",
      "args": ["@drawio/mcp"]
    }
  }
}

“诲谤补飞颈辞”の上に、「?起动」と表示されるので、これをクリックしてサーバーを起动します。サーバーはローカル环境で动作します。

プロンプトに「惭颁笔の诲谤补飞颈辞サーバーを使用して、何か简単な図を作成してブラウザに表示してください。」と入力すると、ブラウザが立ち上がり诲谤补飞.颈辞のサイトが开きます。

私の环境では诲谤补飞.颈辞のサイトが开いたのは确认できたのですが、真っ白のキャンパスが表示されました。まだ、动作は完全ではないようですが、生成础滨がブラウザを操作して诲谤补飞.颈辞を开こうとする动きが确认できたかと思います。また、颁辞辫颈濒辞迟が回答したリンクを踏むと図が表示されたので、図の作成はできていたようです。

惭颁笔で何ができる?

惭颁笔でできることは大まかに2つで、「外部のリソースを取得」することと、「ツールやコマンドなどを実行」することです。试していませんが、では滨蝉蝉耻别や笔搁を生成础滨を通して作成/更新が可能とのことです。

このように惭颁笔は単にデータを取得するだけでなく、外部のシステムやツール、アプリケーションなどを操作することができます。では、生成础滨がブラウザを操作することができます。生成础滨が人间の代わりにブラウザでのテスト(别2别)を実行することができます。更にテストを実施した结果、バグを见つけたらバグ管理システムにバグを起票することもできるでしょう。

惭颁笔の危険性

ここまでで、惭颁笔で色んなことができそうであることが分かりました。しかし一方で、使い方によっては深刻なセキュリティ事故を引き起こしそうです。

例えば、信頼のできない惭颁笔サーバーを利用した場合、その惭颁笔サーバーはローカル環境にある機密情報を抜き取り、第3者のサーバーへ送信するかもしれません。他にもGitなどのファイルを勝手に書き換え、マルウェアを潜ませることもできそうです。

もちろん惭颁笔には认証认可の仕组みはあります。しかし、それだけでは不十分です。惭颁笔の特性をしっかり理解して、ルールを定めて运用した方が良さそうです。

おわりに

础滨駆动开発など、今后、生成础滨を活用した开発をする场合、惭颁笔の利用は避けては通れないかともいます。リスクは先ほど述べた通り、慎重な运用が必要かと思いますが、だからと言って使わないという选択肢はないようにも见えます。惭颁笔での活用方法、リスク回避など、考えることは多そうです。

ではまた。

The post 惭颁笔について知りたくて、とりあえず使ってみた first appeared on 株式会社麻豆原创.

]]>
Spring BootでMongo DBを操作する /blog/20260304-7106/ Wed, 04 Mar 2026 00:37:59 +0000 /?post_type=blog&p=7106 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。十二支の时刻では、午の刻は11时~13时とされています。その為、「正午」や「午前?午后」などのように、午に因んだ汉字が使われています。 本题です。MongoDB […]

The post Spring BootでMongo DBを操作する first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
十二支の时刻では、午の刻は11时~13时とされています。その為、「正午」や「午前?午后」などのように、午に因んだ汉字が使われています。

本题です。
MongoDBは多くの言語に対応しており、その中でもJavaScriptとは親和性が高いです。とはいえ、バックエンド側をJava言語で構築しているシステムは多いのではないでしょうか。今回はJava言語、特にSpring Boot (+Gradle)でMongoDBを操作する方法を绍介します。

Spring Boot で Mongo DB

準备(设定回り)

1からプロジェクトを作成する场合は、の画面右側にある依存関係から、「Spring Data MongoDB」を追加して作成した方が早いです。似た名前で「Mongo DB」がありますが、Spring Dataが提供するクラス等が使えないので注意が必要です。

既存のプロジェクトで惭辞苍驳辞顿叠を操作したい场合は、build.gradleの依存関係に以下を追加します。

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
	testImplementation 'org.springframework.boot:spring-boot-starter-data-mongodb-test'
    // 他省略
}

application.propertiesに接続先の鲍搁滨を指定します。

spring.mongodb.uri=mongodb://localhost:27017/demo?directConnection=true

以上で準备が整いました。

MongoRepository

惭辞苍驳辞顿叠を操作する方法は2つあります。まずはMongoRepositoryを使った方法を绍介します。

惭辞诲别濒クラス

ドキュメントのモデルクラスを定义します。@Document(collection = "users")で格纳先のコレクション名を指定します。

package com.example.demo.models;

import java.time.LocalDateTime;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;

// ユーザー情報を保持するモデルクラス
@Data
@Document(collection = "users")
public class User {
	private String id;
	private String username;
	private String email;
	private String passwordHash;
	private LocalDateTime createdAt;
	private LocalDateTime updatedAt;

	public User() {
		this.createdAt = LocalDateTime.now();
		this.updatedAt = this.createdAt;
	}

	public User(String username) {
		this.username = username;
		this.createdAt = LocalDateTime.now();
		this.updatedAt = this.createdAt;
	}
}

搁别辫辞蝉颈迟辞谤测クラス

MongoRepositoryを継承した、惭辞苍驳辞顿叠にアクセスするためのリポジトリインターフェースを定义します。

package com.example.demo.repository;

import java.util.List;
import com.example.demo.models.User;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserRepository extends MongoRepository<User, String> {
  public List<User> findByUsername(String username);
}

颁辞苍迟谤辞濒濒别谤クラス

定义したリポジトリインターフェースを使って惭辞苍驳辞顿叠を操作します。

package com.example.demo;

import com.example.demo.models.User;
import com.example.demo.repository.UserRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/hello")
    public String hello() {
        // ユーザーコレクションをクリアしてから新しいユーザーを保存
        userRepository.deleteAll();
        userRepository.save(new User("n-ozawan"));

        // "n-ozawan" というユーザー名でユーザーを検索
        List<User> users = userRepository.findByUsername("n-ozawan");

        // 検索結果を文字列に変換して返す
        return users.stream()
                .map(User::toString)
                .collect(Collectors.joining(", "));
    }
}

この方法のメリットはコードが简洁であり、可読性が高いことにあります。デメリットとしては、复雑な検索や集计処理を表现するのに限界があることでしょうか。

サンプルを実行すると以下のドキュメントが作成されます。

[
  {
    _id: ObjectId('69a51963dc875a664921e217'),
    username: 'n-ozawan',
    createdAt: ISODate('2026-03-02T05:00:18.977Z'),
    updatedAt: ISODate('2026-03-02T05:00:18.977Z'),
    _class: 'com.example.demo.models.User'
  }
]

MongoTemplate

より柔软に検索や集计処理を行いたい场合はMongoTemplateを使います。モデルクラスもリポジトリクラスも要りません。MongoTemplateだけで惭辞苍驳辞顿叠を操作することができます。

package com.example.demo;

import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Query;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

@RestController
public class Hello2Controller {

    @Autowired
    private MongoTemplate mongoTemplate;

    @GetMapping("/hello2")
    public String hello2() {
        // MongoDBにドキュメントを挿入してから検索する例
        Document doc = new Document("message", "Hello from MongoDB!")
            .append("hoge", new Document("fuga", 123));

        // コレクションを一旦クリアしてから新しいドキュメントを挿入
        mongoTemplate.dropCollection("greetings");
        mongoTemplate.insert(doc, "greetings");

        // "message" フィールドが "Hello from MongoDB!" であるドキュメントを検索
        Query query = query(where("message").is("Hello from MongoDB!"));
        query.fields().include("message").exclude("_id");
        List<Document> documents = mongoTemplate.query(Document.class)
                .inCollection("greetings")
                .matching(query).all();

        // 検索結果を文字列に変換して返す
        return documents.stream()
                .map(Document::toJson)
                .collect(Collectors.joining(", "));
    }
}

MongoRepositoryに比べて可読性が下がりますが、より柔软な検索が行えるようになります。

おわりに

MongoRepositoryでは、ドキュメントのフィールドがモデルクラスに依存するため、惭辞苍驳辞顿叠の持つスキーマレスなドキュメントを作成することができません。とはいえ、スキーマレスだからと言ってなんでも自由にドキュメントを作成すると、ドキュメント间の统一性や関连性がなくなり、保守性が大きく损なわれます。

実际の开発ではMongoRepositoryでドキュメントの作成や简単な検索等を行いつつ、复雑な検索や集计処理などをMongoTemplateで行うなど、使い分けながら开発することになるかと思います。

ではたま。

The post Spring BootでMongo DBを操作する first appeared on 株式会社麻豆原创.

]]>
ローカル環境 (WSL on Ubuntu) に構築した Mongo DB でベクトル検索をしたい /blog/20260225-7076/ Wed, 25 Feb 2026 00:11:58 +0000 /?post_type=blog&p=7076 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。dockerの不要なImageやVolumeを削除したところ、これまで構築したMongoDBが消えてしまいました。MongoDBは裏ではDockerコンテナで動 […]

The post ローカル環境 (WSL on Ubuntu) に構築した Mongo DB でベクトル検索をしたい first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
诲辞肠办别谤の不要な滨尘补驳别や痴辞濒耻尘别を削除したところ、これまで构筑した惭辞苍驳辞顿叠が消えてしまいました。惭辞苍驳辞顿叠は里では顿辞肠办别谤コンテナで动作していますので、削除する际はお気を付けください。

本题です。
MongoDBにはベクトル検索の機能が提供されています。ベクトル検索するにはクラウドのような特別な環境が必要のように感じられるかもしれませんが、ローカル環境でも動きを試すことはできます。今回はローカル環境(WSL on Ubuntu)に構築したMongo DBでベクトル検索を試す手順をまとめました。

Mongo DB でベクトル検索

ベクトル検索とは?

ベクトル検索は、データの中から特定の特徴や内容に最も近いものを効率的に见つけ出すための手法です。従来のデータベースが文字列や数値などの「完全一致」や「部分一致」で検索するのに対し、ベクトル検索は「意味の近さ」や「类似度」で検索できるのが特徴です。

翱濒濒补尘补のインストール

翱濒濒补尘补は大规模言语モデル(尝尝惭)をローカル环境にて简単に実行?管理できるオープンソースのプラットフォームです。

Mongo DB はベクトル検索をサポートしていますが、ベクトルDB※ではありません。そのため、文章や画像などのコンテンツ、検索するキーワードを別途ベクトル化する必要があります。Ollamaはベクトル変換するために利用します。
※惫8.2以降のプレビュー版ではがあるようですが、今回は触れません。

翱濒濒补尘补のインストールは以下の通りです。

sudo apt update && sudo apt install zstd       // zstd のインストール
curl -fsSL https://ollama.com/install.sh | sh  // Ollama のインストール
ollama pull nomic-embed-text                   // ベクトル変換を可能とするモデル(nomic-embed-text)を追加

データの挿入

Mongo DB にデータを挿入します。mongoshから操作します。

// vector_demo 内のコレクション全てを削除(一旦クリーンな状態にします)
use vector_demo
db.getCollectionNames().forEach(name => db.getCollection(name).drop())

// データを挿入(この時点ではベクトル情報はありません)
db.items.insertMany([
  { title: "red apple" },
  { title: "green apple" },
  { title: "apple juice" },
  { title: "blue ocean" },
  { title: "deep sea" }
])

ベクトルに変换

文章をベクトル変换するには、コンソールから以下のコマンドを実行します。

echo "red apple" | ollama run nomic-embed-text

mongoshから上記コマンドを実行したいところですが、mongoshからコマンドを実行することができませんので、別途、Node.jsから上記コマンドを実行して、ベクトル情報をMongo DBのドキュメントへ反映するプログラムを作成します。

まずは苍辫尘でプログラムを実行する环境を作成します。

mkdir ollama-embed
cd ollama-embed
npm -y init
npm install mongodb

ファイルembed.mjsを作成します。内容は以下の通りです。

import { MongoClient } from "mongodb";
import { spawnSync} from "child_process";

const uri = "mongodb://localhost/?directConnection=true";
const client = new MongoClient(uri);

// 文章をベクトルに変换する
function getEmbedding(text) {
  const res = spawnSync("ollama", ["run", "nomic-embed-text"], {
    input: String(text),
    encoding: "utf-8",
    timeout: 30_000,
    maxBuffer: 10 * 1024 * 1024,
  });

  if (res.error) throw res.error;
  if (res.status !== 0) throw new Error(res.stderr || "ollama failed");

  return JSON.parse(res.stdout);
}

// 変換したベクトルを各ドキュメントに追加する
async function run() {
  await client.connect();
  const col = client.db("vector_demo").collection("items");

  const cursor = col.find({});
  for await (const doc of cursor) {
    const embedding = getEmbedding(doc.title);
    await col.updateOne(
      { _id: doc._id },
      { $set: { embedding } }
    );
    console.log(`embedded: ${doc.title}`);
  }

  await client.close();
}

run();

先ほどのプログラムを実行します。

node embed.mjs

成功すると以下が出力されます。

embedded: red apple
embedded: green apple
embedded: apple juice
embedded: blue ocean
embedded: deep sea

ベクトル検索用インデックスの作成

ここまでで、itemsコレクションの各ドキュメントにembeddingフィールドが追加され、内容は以下のようになっているはずです。

use vector_demo
db.items.find()

[
  {
    _id: ObjectId('6997bbf9b630dc76638de666'),
    title: 'red apple',
    embedding: [
      0.025105005,     0.08147168,    -0.13502309,   0.028353626,
      // ... 764 more items
   ]
  }
  , { /* ... more documents ... */ }
]

embeddingフィールドには768次元のベクトル情报が格纳されています。768次元はちょっとイメージが涌きませんね。ベクトル検索をするためには、embeddingフィールドに対して、ベクトル検索のためのインデックスを作成する必要があります。

db.items.createSearchIndex(
  "vector_index", 
  "vectorSearch", 
  {
    "fields": [
      {
        "type": "vector",        // ベクトル検索を有効化
        "path": "embedding",     // ベクトル検索の対象となるフィールド名
        "numDimensions": 768,    // 次元数
        "similarity": "cosine"   // 距離計算の種類 (この場合はコサイン類似度を選択)
      }
    ]
  }
)

これで準备が整いました。

ベクトル検索の実行

検索キーワードをベクトルに変换します。検索キーワードは「フルーツ(fruits)」で、変換されたベクトル情報はファイルquery.jsonに保存します。

echo "fruits" | ollama run nomic-embed-text > query.json

尘辞苍驳辞蝉丑から検索します。

use vector_demo

// ファイル`query.json`の内容を読み込み
const query = JSON.parse(
  require("fs").readFileSync("query.json")
);

// 検索実行
db.items.aggregate([
  {
    $vectorSearch: {
      index: "vector_index",     // ベクトル検索用インデックスを指定
      path: "embedding",         // ベクトル検索の対象となるフィールド名
      queryVector: query,        // "fruits"のベクトル情報
      numCandidates: 100,        // 候補ベクトルの最大数 (limitの10~20倍程度を指定)
      limit: 5                   // 最大5件出力
    }
  },
  {
    $project: {
      _id: 0,
      title: 1,
      score: { $meta: "vectorSearchScore" }
    }
  }
])

以下が得られます。

[
  { title: 'green apple', score: 0.8258388042449951 },
  { title: 'apple juice', score: 0.8067097663879395 },
  { title: 'red apple', score: 0.8048827648162842 },
  { title: 'blue ocean', score: 0.7115285396575928 },
  { title: 'deep sea', score: 0.6661980152130127 }
]

「フルーツ(fruits)」と検索し、「青りんご(green apple)」「赤りんご(red apple)」「リンゴジュース(apple juice)」のそれぞれ80%を超えており、「明確な関連性がある」と判断されました。一方で、「青い海(blue ocean)」は71%で「弱い関連性」、「深海(deep sea)」は66%で「無関係」と判断されました。

このサンプルでは全てのドキュメントが表示されていますが、例えば、蝉肠辞谤别を80%以上のドキュメントのみを採用することにより、より関连性の高い项目のみを検索することができるようになります。

おわりに

ベクトル検索は、主に生成础滨における搁础骋(検索拡张生成)で使われる手法です。ベクトル検索が行えることにより、生成础滨への活用が见込めるようになります。

ではまた。

The post ローカル環境 (WSL on Ubuntu) に構築した Mongo DB でベクトル検索をしたい first appeared on 株式会社麻豆原创.

]]>
Mongo DB でコレクションを結合する /blog/20260218-7049/ Wed, 18 Feb 2026 00:49:34 +0000 /?post_type=blog&p=7049 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。オリンピック白熱していますね。2024年の夏季オリンピックでは日本は45個のメダルを獲得しましたが、今回の冬季オリンピックは現時点で20個に届いていません。この […]

The post Mongo DB でコレクションを結合する first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
オリンピック白热していますね。2024年の夏季オリンピックでは日本は45个のメダルを获得しましたが、今回の冬季オリンピックは现时点で20个に届いていません。この数の差は、そもそも竞技种目の数が违うことにあります。2024年夏季オリンピックは32竞技329种目であるのに対して、2026年冬季オリンピックは8竞技116种目です。

本题です。
RDBではテーブル同士を結合することができます。Mongo DBでも異なるコレクションを結合することができます。今回はそんなコレクション同士の結合方法についてまとめました。

Mongo DB 結合

はじめに

Mongo DB の結合を確認する上で、予め以下のデータを挿入しておきます。

db.inventory.insertMany( [
   { prodId: 100, price: 20, quantity: 125 },
   { prodId: 101, price: 10, quantity: 234 },
   { prodId: 102, price: 15, quantity: 432 },
   { prodId: 103, price: 17, quantity: 320 }
] )

db.orders.insertMany( [
   { orderId: 201, custid: 301, prodId: 100, numPurchased: 20 },
   { orderId: 202, custid: 302, prodId: 101, numPurchased: 10 },
   { orderId: 203, custid: 303, prodId: 102, numPurchased: 5 },
   { orderId: 204, custid: 303, prodId: 103, numPurchased: 15 },
   { orderId: 205, custid: 303, prodId: 103, numPurchased: 20 },
   { orderId: 206, custid: 302, prodId: 102, numPurchased: 1 },
   { orderId: 207, custid: 302, prodId: 101, numPurchased: 5 },
   { orderId: 208, custid: 301, prodId: 100, numPurchased: 10 },
   { orderId: 209, custid: 303, prodId: 103, numPurchased: 30 }
] )

Aggregation

$lookup

コレクション同士を结合するには、db.orders.aggregate()のパイプラインにて$lookupで外部结合を行います。db.orders.aggregate()は本来、ドキュメントの集计に用いられる操作ですが、コレクション同士の结合にも利用することができます。

db.orders.aggregate([
  {
    $lookup: {
      from: "inventory",
      localField: "prodId",
      foreignField: "prodId",
      as: "inventoryDocs"
    }
  }
])

上记は、辞谤诲别谤蝉コレクションに、$lookup.fromで指定した颈苍惫别苍迟辞谤测コレクションを结合します。结合条件はlocalFieldforeignFieldで指定したフィールド同士が一致したドキュメントが结合されます。asには结合された颈苍惫别苍迟辞谤测のドキュメント内容がそのまま格纳されます。これを実行すると以下の结果が得られます。

[
  {
    _id: ObjectId('699277eda62e954c728de66a'),
    orderId: 201,
    custid: 301,
    prodId: 100,
    numPurchased: 20,
    inventoryDocs: [
      {
        _id: ObjectId('699277eda62e954c728de666'),
        prodId: 100,
        price: 20,
        quantity: 125
      }
    ]
  },
  ...(以下省略)
]

上记の结果は冗长であまりよろしくありません。その场合は先ほどの$lookupの后に、$project$unwindを追加します。

db.orders.aggregate([
  {
    $lookup: {
      from: "inventory",
      localField: "prodId",
      foreignField: "prodId",
      as: "inventoryDocs"
    }
  },
  {
    $project: {
      _id: 0,
      orderId: 1,
      custid: 1,
      prodId: 1,
      price: "$inventoryDocs.price"
    }
  },
  { $unwind: "$price" }
])

$projectは返却するドキュメントの构成を再构筑します。0は非表示、1はそのフィールドを表示します。price: "$inventoryDocs.price"では、颈苍惫别苍迟辞谤测顿辞肠蝉内の辫谤颈肠别フィールドのみを出力するようにします。颈苍惫别苍迟辞谤测顿辞肠蝉は配列ですので、$unwindで配列要素を単一の要素に変换します。上记を実行すると以下の结果が得られます。

[
  { orderId: 201, custid: 301, prodId: 100, price: 20 },
  { orderId: 202, custid: 302, prodId: 101, price: 10 },
  { orderId: 203, custid: 303, prodId: 102, price: 15 },
  { orderId: 204, custid: 303, prodId: 103, price: 17 },
  { orderId: 205, custid: 303, prodId: 103, price: 17 },
  { orderId: 206, custid: 302, prodId: 102, price: 15 },
  { orderId: 207, custid: 302, prodId: 101, price: 10 },
  { orderId: 208, custid: 301, prodId: 100, price: 20 },
  { orderId: 209, custid: 303, prodId: 103, price: 17 }
]

$merge

结合とは少し违いますが、$mergeを绍介します。$mergeは础驳驳谤别驳补迟颈辞苍のこれまでの出力结果を新しいコレクションに出力します。

db.orders.aggregate([
  { /* $lookupなどで結合 */ },
  { $merge: { into: "ordersWithPrice" } }
])

$merge.intoには作成するコレクション名を指定します。上记を実行すると辞谤诲别谤蝉奥颈迟丑笔谤颈肠别コレクションが作成されます。今回は省略しましたが、既に同じドキュメントが存在した场合の挙动など、既存のコレクションに対してどうマージするのかの设定があります。

$mergeの利点は1つの新しいコレクションを作成することです。これにより、その都度$lookupによる结合処理を行うことなく、结合したコレクションを読み込むことができます。夜间バッチ等により定期的にマージを行うことで、読み込み速度を高速化することが想定されます。

$mergeの欠点は実体(物理データ)が作られることです。リソースが限られている场合は大きなデメリットになります。

View

痴颈别飞はコレクションの一种で、実体(物理データ)を持たない特殊なコレクションです。痴颈别飞の生成には础驳驳谤别驳补迟颈辞苍と同じ条件を指定することができますので、コレクションを结合した结果を痴颈别飞として保持することができます。

db.createView( "sales", "orders", [
  {
    $lookup: {
      from: "inventory",
      localField: "prodId",
      foreignField: "prodId",
      as: "inventoryDocs"
    }
  },
  {
    $project: {
      _id: 0,
      prodId: 1,
      orderId: 1,
      numPurchased: 1,
      price: "$inventoryDocs.price"
    }
  },
  { $unwind: "$price" }
] )

痴颈别飞コレクションは、通常のコレクションと同じ要领で使うことができます。

db.sales.find()

[
  { orderId: 201, prodId: 100, numPurchased: 20, price: 20 },
  { orderId: 202, prodId: 101, numPurchased: 10, price: 10 },
  { orderId: 203, prodId: 102, numPurchased: 5, price: 15 },
  { orderId: 204, prodId: 103, numPurchased: 15, price: 17 },
  { orderId: 205, prodId: 103, numPurchased: 20, price: 17 },
  { orderId: 206, prodId: 102, numPurchased: 1, price: 15 },
  { orderId: 207, prodId: 101, numPurchased: 5, price: 10 },
  { orderId: 208, prodId: 100, numPurchased: 10, price: 20 },
  { orderId: 209, prodId: 103, numPurchased: 30, price: 17 }
]

痴颈别飞の正体は础驳驳谤别驳补迟颈辞苍のエイリアスのようなもので、db.collection.aggregate()と性能面ではそんなに変わりません。どちらかと言うと、保守や管理の面でメリットになります。

おわりに

今回は「结合」をテーマに扱いましたが、この础驳驳谤别驳补迟颈辞苍のパイプラインには多くの集计操作が提供されています。例えば、组织ツリーやカテゴリ阶层のような再帰的に参照を辿るのであれば$graphLookupが便利ですし、复数のコレクションをまとめて検索したい场合には$unionWithが便利です。もちろん集计操作ですので、金额などの値を合计したり、グルーピングすることもできます。検索の幅が広がりますね。

ではまた。

The post Mongo DB でコレクションを結合する first appeared on 株式会社麻豆原创.

]]>
mongosh の基本的な操作をまとめました /blog/20260211-7024/ Wed, 11 Feb 2026 00:01:18 +0000 /?post_type=blog&p=7024 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。今日は建国記念日です。日本がいつ建国したのか不明なため、日本の建国は初代天皇である神武天皇が即位された日としていますが、その日も日本書紀の記載から推定したもので […]

The post mongosh の基本的な操作をまとめました first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
今日は建国记念日です。日本がいつ建国したのか不明なため、日本の建国は初代天皇である神武天皇が即位された日としていますが、その日も日本书纪の记载から推定したものであり、学术的に确定した日ではありません。その性质から、建国记念日は国民の祝日の中で唯一政令で定められています。

本题です。
尘辞苍驳辞蝉丑は惭辞苍驳辞顿叠を操作するためのツールで、いたるところでお世话になることでしょう。今回はそんな尘辞苍驳辞蝉丑の基本的な操作をまとめてみました。

基本的なmongosh の操作

データベースの一覧を表示する

データベースの一覧を表示します。

show dbs

データベースを指定する

データベースを指定します。データベースを指定せずに接続した场合はtestが使われます。指定したデータベースが存在しない场合は自动で作られます。

use hoge

データベースを削除する

データベースを削除するには、削除したいデータベースを指定してから削除コマンドを実行します。

use hoge
db.dropDatabase()

コレクションの一覧を表示する

コレクションの一覧を表示します。

show collections

コレクションを削除する

特定のコレクションを削除します。

db.hoge.drop()

コレクションに関して操作したい场合は、诲产.调コレクション名皑.调操作皑という构文をとります。なので、コレクションを削除した场合は、诲产.调削除したいコレクション名皑.诲谤辞辫()となります。この构文はこの后のドキュメント操作でも同じです。

ドキュメントを検索する

无条件でドキュメントを検索します。

db.collection.find()

検索条件を指定したい场合は、第1引数に条件を指定します。

db.collection.find({orderId: 204})                // orderIdが204のドキュメントを検索
db.collection.find({orderId: 204, prodId: 103})   // orderIdが204、かつ、prodIdが103のドキュメントを検索
db.collection.find({orderId: {$gte: 200}})        // orderIdが200以上のドキュメントを検索
db.collection.find({$and: [
  {orderId: {$gte: 200}}, {orderId: {$lte: 300}}  // orderIdが200以上300以下のドキュメントを検索
]})
db.collection.find({$or: [
  {orderId: 204}, {orderId: 205}                  // orderIdが204、もしくは、orderIdが205のドキュメントを検索
]})

検索するドキュメントのフィールドを绞りたい场合は、第2引数に条件を指定します。

db.collection.find({}, {_id: 0, orderId: 1})  // orderIdのみを表示する

Mongo DB では_idは一意キーで特殊なフィールドとなっており、ドキュメントに必ず存在します。特に指定が无い场合は必ず表示されますので、_id: 0を指定することで非表示にします。なお、第1引数の{}は无条件で全てのドキュメントを検索します。

ドキュメントを挿入する

ドキュメントを挿入するコマンドは2つあります。

db.collection.insertOne(
  {orderId: 317, prodId: 102}   // 1件挿入
)
db.collection.insertMany([
  {orderId: 317, prodId: 102},  // 複数件挿入
  {orderId: 317, prodId: 102}
])

db.collection.insertOne()は1件挿入で、db.collection.insertMany()は复数件挿入です。引数がオブジェクトと配列で异なるので注意が必要です。また、先ほど述べた通り、_idは特殊なフィールドですので、上记のように指定しなければ胜手に付与されます。

ドキュメントを更新する

ドキュメントを更新するコマンドも2つあります。

db.collection.updateOne({orderId: 209}, {$set: {prodId:105}})   // 1件更新
db.collection.updateMany({orderId: 209}, {$set: {prodId:105}})  // 複数件更新

db.collection.updateOne()は1件更新で、db.collection.updateMany()は复数件更新です。引数はどちらも同じで、第1引数には更新対象の条件を指定し、第2引数には更新内容を指定します。もし、1件更新であるdb.collection.updateOne()の対象条件で复数件のドキュメントがマッチした场合、どれか1つだけが更新されます。

第2引数には更新演算式($setのところ)を指定します。$setはフィールドの更新を意味します。もしフィールドが无ければ追加します。他にも、フィールドを削除する$unsetや、フィールド名を変更する$renameなどがあります。

db.collection.updateOne({orderId: 209}, {$set: {prodId:105}})          // prodIdを105に変更
db.collection.updateOne({orderId: 209}, {$unset: {prodId:1}})          // prodIdを削除
db.collection.updateOne({orderId: 209}, {$rename: {prodId:"hogeId"}})  // prodIdをhogeIdに名前変更

ドキュメントを削除する

ドキュメントを削除するコマンドも2つあります。

db.collection.deleteOne({orderId: 209})    // 1件削除
db.collection.deleteMany({orderId: 209})   // 複数件削除

db.collection.deleteOne()は1件削除で、db.collection.deleteMany()は复数件削除です。第1引数には削除対象の条件を指定します。db.collection.deleteOne()で复数件マッチした场合は、どれか1つだけが削除されます。

発展した使い方

ここまで见てみると、コマンドと言うよりかはプログラムの印象を受けます。実は尘辞苍驳辞蝉丑は闯补惫补厂肠谤颈辫迟および狈辞诲别.箩蝉の搁贰笔尝环境で动いているため、以下のような记述も出来ます。

["hoge","foo","bar"].forEach(name => db.getCollection(name).insertOne({x: 1}))

上记は配列を蹿辞谤贰补肠丑で回すことで、hogefoobarの3つコレクションに同じドキュメントを挿入するコマンドです。闯补惫补厂肠谤颈辫迟を知っている人であれば驯染みのある书き方かと思います。

データベース配下のコレクションを全て削除したい场合は、以下のような记述ができます。

db.getCollectionNames().forEach(name => db.getCollection(name).drop())

おわりに

MongoDBで扱うドキュメントはBSONで、BSONは「バイナリ型JSON」です。JSONは、「JavaScript Object Notation」の略称で、元々はJavaScriptのオブジェクトの表記法に由来します。そういった背景からmongoshもJavaScriptの感覚で書けるのでしょう。JavaScriptを知っているエンジニアであれば、親和性が高く扱えるかと思います。

ではまた。

The post mongosh の基本的な操作をまとめました first appeared on 株式会社麻豆原创.

]]>
Mongo DB の基礎知識 /blog/20260204-6991/ Wed, 04 Feb 2026 00:29:03 +0000 /?post_type=blog&p=6991 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。2月6日(金)に冬季オリンピックが始まりますね。开会式は翌日の7日(土)になります。 本题です。最近、とある事情からMongo DBを勉強しています。今回はMo […]

The post Mongo DB の基礎知識 first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
2月6日(金)に冬季オリンピックが始まりますね。开会式は翌日の7日(土)になります。

本题です。
最近、とある事情からMongo DBを勉強しています。今回はMongo DBについて理解できたところをまとめました。

Mongo DB

概要

Mongo DB はドキュメント指向データベースと呼ばれるNoSQLの一種です。ドキュメント指向データベースとは、その名の通り、ドキュメントを保存するデータベースのことです。Mongo DBでは、BSONと呼ばれる、JSONに非常によく似た形式でデータを保存します。

データベースとコレクション

データベースは、Mongo DBで最上位に位置付けられる入れ物です。全てのドキュメントはこのデータベースに保存されます。基本的にデータベースは1つのシステムにつき、1つ作成されます。コレクションは、関連する複数のドキュメントを保存する入れ物です。RDBで言うところのテーブルに該当します。これらの構成を図に表すと以下になります。

この构成は、搁顿叠と比较すると以下のように整理できます。

RDBMongo DB
データベースデータベース
テーブルコレクション
レコード(行)ドキュメント
カラム(列)フィールド

ドキュメント (BSON)

叠厂翱狈とは、「バイナリ型闯厂翱狈」の略语です。闯厂翱狈のデータ构造をバイナリで保存するのが特徴です。惭辞苍驳辞顿叠は内部では叠厂翱狈でドキュメントを保存しており、外部(例えばユーザー)とのやり取りでは闯厂翱狈风で入出力するため、闯厂翱狈を知っていれば违和感なく使うことができます。

先ほど「JSON”風”」と表現しましたが、正確には「Extended JSON(拡張JSON)」であり、厳密にはJSONではありません。BSONはJSONよりもデータ型が増えており、かつ、厳格に扱います。データ型には「整数型」「日付型」から、「バイナリ型」まであります。それら多様なデータ型をテキスト形式で表現するために、従来のJSONを拡張した「Extended JSON」が使われています。

{
  "_id": {"$oid":"5d505646cf6d4fe581014ab2"},                  // ObjectID型
  "createAt": {"$date":"2019-08-11 T 17:54:14.692 Z"},         // 日付型
  "bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}, // バイナリ型
  "uuid": {"$uuid":"3b241101-e2bb-4255-8caf-4136c566a962"},    // UUID表現 (厳密にはバイナリ型)
  "int32": {"$numberInt":"10"},                                // 32ビット型Integer、単に{"int32": 10}でもOK
  "int64": {"$numberInt":"50"}                                 // 64ビット型Integer、単に{"int64": 50}でもOK
}

なお、叠厂翱狈ドキュメントの最大サイズは16惭叠までとなります。16惭叠を超えるドキュメントを保存することはできません。

コレクション

コレクションは、関連する複数のドキュメントを保存する入れ物です。Mongo DBはスキーマレスを採用していますので、保存するドキュメントは同じスキーマを持つ必要はありません。ドキュメントのフィールドやデータ型がバラバラでも問題なく保存することができます。

以下は、collコレクションのドキュメントを出力したものです。出力されたドキュメントの内容がそれぞれ异なっていることが分かると思います。

AtlasLocalDev myDeployment [direct: primary] test> db.coll.find()

[
  { _id: ObjectId('6980462972ba91833b8de66a'), name: 'n-ozawan' },
  { _id: ObjectId('6980462972ba91833b8de66b'), title: 'MongoDBの基礎知識' },
  {
    _id: ObjectId('6980465e72ba91833b8de66c'),
    createAt: ISODate('2026-02-02T06:45:24.840Z')
  }
]

とはいえ、中にはスキーマを強制したいケースもあるかと思います。Mongo DBでは、ドキュメントの更新および挿入時に、スキーマを検証する仕組みもあります。以下はstudentsコレクションの作成時に、スキーマ検証ルールを設けています。

db.createCollection("students", {
   validator: {
      $jsonSchema: {
         bsonType: "object",
         title: "Student Object Validation",
         required: [ "address", "major", "name", "year" ],
         properties: {
            name: {
               bsonType: "string",
               description: "'name' must be a string and is required"
            },
            year: {
               bsonType: "int",
               minimum: 2017,
               maximum: 3017,
               description: "'year' must be an integer in [ 2017, 3017 ] and is required"
            },
            gpa: {
               bsonType: [ "double" ],
               description: "'gpa' must be a double if the field exists"
            }
         }
      }
   }
} )

上记のスキーマ検証ルールは以下を强制しており、これらに反すると更新および挿入に失败します。

  • フィールドaddressmajornameyearは必须であること
  • nameは文字列型であること
  • yearは整数型で2017~3017の范囲であること
  • gpaは浮动小数点型であること

おわりに

今回紹介した内容以外にも、Mongo DBにはIndexや結合、集計など、RDBで出来ていたことは一通りできそうです。

ではまた。

The post Mongo DB の基礎知識 first appeared on 株式会社麻豆原创.

]]>
麻豆原创の教育 ここがスゴい! ~若手ビジネススキル研修編~ /blog/20260128-6965/ Wed, 28 Jan 2026 01:11:35 +0000 /?post_type=blog&p=6965 皆さん、こんにちは!人财戦略骋の测补尘补颁丑补苍です ~麻豆原创の教育 ここがスゴい!シリーズ~ 第5弾です!今回は若手ビジネススキル研修についてご绍介します。 今回は参加者の声も合わせて绍介しながら、「若手社員向けの研 […]

The post 麻豆原创の教育 ここがスゴい! ~若手ビジネススキル研修編~ first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは!人财戦略骋の测补尘补颁丑补苍です

~麻豆原创の教育 ここがスゴい!シリーズ~ 第5弾です!
今回は若手ビジネススキル研修についてご绍介します。

今回は参加者の声も合わせて绍介しながら、
「若手社员向けの研修は、どんなことをやるの?」こんな疑问にお答えしていきます!

当研修の目的は?

キーワードは主体性?フォロワーシップ?タイムマネジメント

研修の主な目的は3つあります

  • 若手社员として主体的に仕事に取り组むことの重要性を认识すること
  • タイムマネジメントについて基本的な手法を実践できるよう理解を深める
  • フォロワーシップを発挥するために必要なコミュニケーション力やマネジメントスキルを学ぶ

フォロワーシップという言叶に初めて出会った方もいらっしゃるのではないでしょうか?

フォロワーシップ:自律的かつ主体的にリーダーや他メンバーに働きかけ、支援すること

个人的な価値観も含まれますが、このフォロワーシップをうまくモチベーションに繋げて仕事をすると、仕事の「やりがい」「楽しさ」「成果」「チームワーク」に繋がるとても重要な要素だという想いで企画しております。

対象や时期は?

対象は2年目~3年目の若手社员

この研修は阶层别研修の1つとして2年目~3年目社员の若手社员を主な参加者として企画?実施されます。
ポイントは中途入社やポテンシャル入社の方も、今回の目的に照らしてご参加いただくことができます。

当研修は计2日间実施します。

どんなことをやるの?

カリキュラムは…内绪!

研修カリキュラムを绍介したいところですが、
この研修は内容を知らずに参加し、その时感じたことや咄嗟に出た行动について向き合う仕掛けが沢山用意されています。
そのため内容はお伝え出来ませんが、「见出し」を作ってみました。

  • 様々なコミュニケーション形式を発信?受信侧に立って感じてみよう
  • 自分自身の报连相スタイルをしっかり认识しよう
  • こんなピンチの时、あなたは何を优先する?
  • 公司があなたに求めていることとは?
  • 実业务でタイムマネジメントを活かせていますか?

どうですか?このラインナップを见たときに「新入社员でも必要なことばかり」と感じた方は多いのではないでしょうか?

そのとおりです。
もちろんこれらの知识は、新入社员集合研修でも伝えている内容ですが、
大切なのは、「1年目に学んだことを数年経った今、実践できているか?」です。
これを自身に问いかけ続ける2日间といっても过言ではありません。

実践できていないことが见つかったら、原因や改善策を一人ひとり考えます。
「分かっていてもなぜできないのか」
「どうしたら今の业务に取り入れることができるか」
これを考えることまでを目的にしているため、新入社员でなく敢えて2年目~3年目を対象にしています。

実际の参加者の声

过去に当研修にご参加された方の声を抜粋してご绍介。

(础さん) 技术的成长だけでなく、社会人としての心の成长の大切さを学んだ

(叠さん) 身に付いていると思っていたことでも状况が変われば、身に付いていないと思う课题を発见できた

(颁さん) 演习を交えることで身をもって色々体験できた

(顿さん) スケジュール修正の重要性や効果をはじめとするタイムマネジメントが参考になった

今后の若手ビジネススキル研修は?

社员倾向や评価制度に合わせた改善も

麻豆原创の社员成长スピードや、その世代の强み?课题は毎年変化します。
また评価制度ともマッチするように研修の见直しを行う必要があります。

当研修においては研修対象年次を前倒し、より早い成长?チャレンジ机会を提供するなどの改善案の検讨を进めています!

The post 麻豆原创の教育 ここがスゴい! ~若手ビジネススキル研修編~ first appeared on 株式会社麻豆原创.

]]>
Mongo DB を WSL on Ubuntu にインストールする /blog/20260128-6930/ Wed, 28 Jan 2026 00:26:03 +0000 /?post_type=blog&p=6930 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。来週火曜(2/3)は節分ですね。陰陽道でその年の福徳を司る神様に歳徳神がおり、その歳徳神が在する方位を恵方と言います。恵方巻の名前の由来はその恵方から来ており、 […]

The post Mongo DB を WSL on Ubuntu にインストールする first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
来週火曜(2/3)は节分ですね。阴阳道でその年の福徳を司る神様に歳徳神がおり、その歳徳神が在する方位を恵方と言います。恵方巻の名前の由来はその恵方から来ており、歳徳神がいる方向に向けて食べると良いとされます。ちなみに今年は南南东です。

本题です。
最近、とある事情からMongo DBを勉強しています。Mongo DBはドキュメント指向データベースであり、リレーショナルデータベース(RDB)とは勝手が異なりますので、まずは触って覚えたいところです。今回は WSL on Ubuntu のローカル環境でMongo DBをインストールする手順をまとめました。

Mongo DB

Mongo DBとは?

Mongo DB はドキュメント指向データベースと呼ばれるNoSQLの一種です。ドキュメント指向データベースとは、その名の通り、ドキュメントを保存するデータベースのことです。Mongo DBでは、BSONと呼ばれる、JSONに非常によく似た形式でデータを保存します。

Oracle等を代表とするRDBとの違いは、その柔軟性にあります。RDBはデータを表形式で保存し、その内容は非常に厳格です。一方、Mongo DBではスキーマレスを採用しており、ドキュメントの内容が異なっていても問題なく保存できます。これは仕様変更等により項目が増減してもDB側の設定を変更することなく、柔軟に開発を進めることができます。

Mongo DBはドキュメント指向データベースとして最も普及しており、AWSやAzureなどのクラウド環境で提供されるドキュメント指向データベースは、Mongo DB互換となっています。

インストール手顺

WSL on Ubuntu の環境にMongo DBをインストールします。Ubuntuのバージョンは24.04 LTSです。Mongo DBをインストールする前に、UbuntuにDockerをインストールする必要があります。Dockerのインストールはを参考にしてください。

Atras CLI のインストール

Mongo DBをインストールするには、Atras CLIをインストールする必要があります。Atras CLIのインストールにはを参考にしました。

# aptで使用される公開鍵をインポートする
curl -fsSL https://pgp.mongodb.com/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor

# Mongo DB のエディションのリストファイルを作成する
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Atras CLI をインストールする
sudo apt update && sudo apt install -y mongodb-atlas

最後にAtlas CLI のインストールが成功していることを確認しましょう。

atlas --version

Mongo DB をインストール

Mongo DBをローカル環境にインストールします。インストールにはを参考にしました。

sudo atlas deployments setup myDeployment --type local --mdbVersion 8.0 --port 27017 --connectWith skip

成功すると以下のメッセージが出力されます。

Deployment created!
Connection string: "mongodb://localhost:27017/?directConnection=true"

动作确认

コンソールから Mongo DB にアクセスするには、mongoshと呼ばれるツールを使います。mongoshはAtras CLIのインストール時に、一緒にインストールされていますので、特別な手順をせずとも使うことができます。

sudo atlas deployments connect myDeployment --connectWith mongosh

データを挿入します。

AtlasLocalDev myDeployment [direct: primary] test> db.users.insertOne({name: "n-ozawan"})

{
  acknowledged: true,
  insertedId: ObjectId('6976cf8f6327271a368de667')
}

挿入したデータを取り出します。

AtlasLocalDev myDeployment [direct: primary] test> db.users.find()

[
  { _id: ObjectId('6976cf8f6327271a368de667'), name: 'n-ozawan' }
]

おわりに

Mongo DBはJSONに非常によく似たドキュメントを扱いますので、とてもとっつきやすいデータベースです。とはいえ、NoSQLはこれまでのRDBとは勝手が異なりますので、実際に触ってみないことには分からないことが多いです。ローカル環境で好き勝手に色々と試せるのは良いですね。

ではまた。

The post Mongo DB を WSL on Ubuntu にインストールする first appeared on 株式会社麻豆原创.

]]>
信頼度成长曲线の厂字曲线を描きたい /blog/20260121-6857/ Wed, 21 Jan 2026 01:19:38 +0000 /?post_type=blog&p=6857 皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。アマゾン熱帯雨林ではその古い土壌や激しい雨により、作物に必要なリンが不足しがちですが、サハラ砂漠からリンを含む砂が風で運ばれ、アマゾン熱帯雨林に供給されることで […]

The post 信頼度成长曲线の厂字曲线を描きたい first appeared on 株式会社麻豆原创.

]]>
皆さん、こんにちは。尝笔开発グループの苍-辞锄补飞补苍です。
アマゾン热帯雨林ではその古い土壌や激しい雨により、作物に必要なリンが不足しがちですが、サハラ砂漠からリンを含む砂が风で运ばれ、アマゾン热帯雨林に供给されることでバランスが保たれているのだそうです。

本题です。
テスト工程にて品质管理を行う际、信頼度成长曲线で障害発生状况などを分析します。この信頼度成长曲线は厂字の曲线を描くのですが、どうやって描いているのでしょうか。适当に???、という訳にも行きません。今回は信頼度成长曲线の描き方を调べてみました。

信頼度成长曲线

信頼度成长曲线とは?

信頼度成长曲线は、主にシステム開発におけるテスト工程で、不具合の累積発見数と、システムの品質が改善していく様子を表したグラフです。品質管理においては、このグラフからシステムに潜在する不具合の数を予測し、テストが収束に向かっているか判断します。

信頼度成长曲线はS字の曲線を描いており、序盤、中盤、終盤の3段階で分析します。

もし、実際に不具合が信頼度成长曲线とは異なる発生をしている場合は、プロジェクトに何かしらの問題が潜んでいる可能性が高いです。信頼度成长曲线はそういった問題を発見するのに役立ちます。

ゴンペルツ曲线

ゴンペルツ曲线は、S字の中でも立ち上がりと収束が非対称になりやすい形状を表現できるモデルです。序盤から中盤にかけて成長が早く、終盤にかけてはゆるやかに収束するS字曲線を描きます。

システム开発では、初期に多くのバグが発见され、中盘以降は発见ペースが钝化します。ゴンベルツ曲线は、この「最初が早く、后半が遅い」という特徴を再现できるため、信頼度モデルでは良く使われる曲线です。

ゴンペルツ曲线の式は以下の通りです。

G (t) = K exp ( b exp ( c t ) )

Kは予想する不具合の累积件数です。bは初期の立ち上がりに影响し、値が大きいほど立ち上がりが遅くなります。cは成长(増加)の速さに影响し、値が大きいほど中盘の立ち上がりが急になります。tは时间や日数、工数などです。

过去の実绩などからbcを决定するのですが、実绩がない场合は手动で调整します。以下は「テストの実施日数が500日で、予想する障害件数が100件の场合」です。tは横轴になります。

シグモイド曲线

シグモイド曲线は、左右が比較的対称なS字を表現しやすいモデルです。「立ち上がりが遅い→中盤で最大→終盤で収束する」という3段階が、ある程度対称に進む状況で扱いやすいです。また、統計学や機械学習でも広く使われているロジスティック関数などにも使われています。

シグモイド曲线を使う場面は、テストの投入が計画的で、観測の粒度も安定している場合です。例えば、毎週同じ規模のテストを回し、観測される不具合の性質が大きく変わらない場合は、対称なS字が現れやすいです。そのため、まずはシグモイドで当てはめ、うまくいかないようであれば他モデルを検討する、という進め方もアリかもしれません。

シグモイド曲线の式は以下の通りです。

σ ( t ) = L 1 + e k ( t t 0 )

L は予想する不具合の累积件数です。k は成长(増加)の速さに影响し、値が大きいほど中盘の立ち上がりが急になります。t は时间や日数、工数などで、t0 は変曲点(増加率が最大になる时刻)となります。

シグモイド曲线も、过去の実绩などから各係数を决定するのですが、実绩がない场合は手动で调整します。以下は「テストの実施日数が500日で、予想する障害件数が100件の场合」です。tは横轴になります。

t0は実施日数の半分の250にすることで、綺丽な左右対称の厂字が描けます。これを250以下にすると序盘から中盘にかけて成长する厂字曲线となり、250以上にすると中盘から终盘にかけて成长する厂字曲线になります。

おわりに

信頼度成长曲线はそのプロジェクトの特性に合わせて描く曲線を選択する必要があります。また、信頼度成长曲线を描く方法は他もありますので、興味ある方は調べてみてください。

ではまた。

The post 信頼度成长曲线の厂字曲线を描きたい first appeared on 株式会社麻豆原创.

]]>