Docs Menu
Docs Home
/ /

MongoDBと Nux および Vue との統合

このチュートリアルでは、Vue を使用しMongoDBと統合する Nuxtアプリケーションの作成について説明します。 Nux は、ファイルベースのルーティング、サーバー側のレンダリング、および nitroサーバーエンジンを通じて組み込みAPIルートを提供する Vueフレームワークです。 Nux を Vue と組み合わせると、別の バックエンドサーバーなしで完全なアプリケーションを構築できます。

このチュートリアルのアプリケーションには、次のレイヤーが含まれています。

  • データベースレイヤー: MongoDB は、データのストレージと取得を提供します

  • サーバーレイヤー: NuxサーバールートはAPIロジックとデータベースインタラクションを処理します

  • プレゼンテーションレイヤー: Vue は、リアクティブなデータ バインディングを持つユーザー インターフェイスを実装します

Vue で Nux をビルドすると、サーバールート用のNode.jsランタイムを備えたフルスタックフレームワークが提供され、 MongoDB Node.jsドライバーに自然に適合します。 Nuxサーバールートまたはサーバーサイド ユーティリティから直接MongoDBに接続し、別のバックエンド サービスやAPIレイヤーを維持することなく、ドキュメントを Vue コンポーネントに返すことができます。

MongoDB の柔軟なドキュメント構造はJavaScriptオブジェクトに簡単にマップされます。その結果、 オプションAPI を使用しているか、 コンフィギュレーションAPI を使用しているかにかかわらず、Vue コンポーネント内のMongoDBデータをシームレスに操作できます。 MongoDBから取得したドキュメントは、コンポーネントとテンプレートに直接渡すことができるため、複雑なデータ変換や追加の オブジェクト関係マッピング(ORM)レイヤーの必要性を減らします。

Nux のサーバーサイド レンダリング(SSR)とデータ取得ユーティリティを使用すると、ページをレンダリングする前にサーバー上のMongoDB をクエリできます。これにより、Vue コンポーネントをすぐに使用できるデータで満たすことができ、データ駆動型アプリケーションの認識パフォーマンスと SE が向上します。

このチュートリアルでは、nux と Vue を使用してウェブアプリケーションを構築する方法を説明します。アプリケーションはサンプルレストラン データにアクセスし、データをクエリし、その結果をローカルでホストされているサイトに表示します。このチュートリアルには、 MongoDB AtlasでホストされているMongoDBクラスターに接続し、データベースからのデータにアクセスして表示する手順も含まれています。

Tip

Nux なしでNode.jsドライバーを使用してMongoDBに接続する場合は、 「 Node.jsドライバーを使い始める 」ガイドを参照してください。

このセクションの手順に従って、プロジェクトの依存関係のインストール、Atlas クラスターの作成、アプリケーションディレクトリの設定を行います。

1

クイック スタートアプリケーションを作成するには、開発環境に次のソフトウェアをインストールします。

前提条件

ノート

バージョン 20 以降を使用します。

コードエディター

このチュートリアルでは Visual Studio Code を使用しますが、お好みのエディターを使用できます。

ターミナルアプリとシェル

macOS ユーザーまたはLinuxユーザーの場合は、 ターミナル または 類似アプリを使用します。 Windowsユーザーの場合は、 PowerShell を使用します。

2

MongoDB Atlas は、 MongoDB配置をホストするフルマネージドクラウドデータベースサービスです。 MongoDBデプロイいない 場合は、 「 MongoDBを使い始める 」チュートリアルを完了することで、 MongoDBクラスターを無料で作成できます(クレジットカードは不要)。

Tip

sample_restaurantsデータセットがクラスターにロードされていることを確認します。このチュートリアルでは、そのデータセットのデータをクエリします。sample_restaurants データセットをクラスターにロードする方法については、 「 MongoDBを使い始める 」チュートリアルを参照してください。

MongoDBクラスターに接続するには、接続 URI を使用する必要があります。接続文字列を検索する方法については、MongoDBを使い始めるチュートリアルの接続文字列の追加セクションを参照してください。

Tip

MongoDB Atlas接続文字列を安全な場所に保存します。これを後の手順で .envファイルに追加します。

3

公式の Nux t CLI を使用して、新しい NuxプロジェクトをVue で初期化します。ターミナルを開き、目的のプロジェクトディレクトリに移動します。

初期化コマンドを実行します。

npm create nuxt@latest

CLI はプロジェクトを設定する ように要求します。次の応答を使用します。

  1. プロンプト: 次のパッケージをインストールする必要があります: create-nuxt@ latest-number続行しますか。

    応答: y「 」と入力して Enter キーを押します。

  2. プロンプト:どのテンプレートを使用しますか。

    応答: minimal - Minimal setup for Nuxt 4 (recommended)を選択します。

  3. プロンプト:プロジェクトをどこで作成しますか?

    応答:デフォルトのディレクトリを受け入れるか、別のパスを入力するには Enterを押します。

  4. プロンプト: どのパッケージマネージャーを使用しますか。

    応答: npmを選択します。

  5. プロンプト: Gitリポジトリを初期化しますか?

    応答: YesNo優先設定に基づいて または を選択します。

  6. プロンプト:公式のモジュールをインストールしますか。

    応答: Noを選択します。

4

プロジェクトディレクトリに移動し、次のコマンドを実行中て、 MongoDBドライバー、 Lucid アイコン、tailwind、および関連する依存関係をインストールします。

npm install mongodb lucide-vue-next
npm install -D @types/node @nuxtjs/tailwindcss

tailwind インストールから非推奨パッケージに関する警告を無視しても問題ありません。

プロジェクト構造を設定したら、このセクションの手順に従ってバックエンドを設定します。

1

プロジェクトのルートに .envファイルを作成し、プロジェクトルートで次のコマンドを実行中て接続 URI を安全に保存します。

touch .env

.envファイルを開き、接続 URI を追加します。

MONGODB_URI=<Your Connection URI>

注意

<Your Connection URI> をMongoDB Atlasから受信した接続 URI に置き換えます。

2

プロジェクトルートで nuxt.config.tsファイルを開き、その内容を次のコードで置き換えて、環境変数をロード、tailwind CSS モジュールを構成します。

nux.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
future:{
compatibilityVersion: 4,
},
runtimeConfig:{
// Server-side only config. Not exposed to the client
mongoURI: process.env.MONGODB_URI,
},
css:['@/assets/css/main.css'],
modules: ['@nuxtjs/tailwindcss'],
})

nuxt.config.tsファイルは.envファイルから環境変数をロードし、Vue コンポーネントのスタイルを設定するための Railwind サポートを構成します。

3

プロジェクトルートで次のコマンドを実行して、 MongoDB接続ロジックを保持するためのユーティリティファイルを作成します。

mkdir -p server/utils
touch server/utils/mongodb.ts

server/utils/mongodb.tsファイルを開き、次のコードを追加します。

サーバー/uts/mongodb.ts
import { MongoClient, type Db } from "mongodb";
let cachedClient: MongoClient | null = null;
let cachedDb: Db | null = null;
export async function connectToDatabase(){
if (cachedClient && cachedDb){
return { client: cachedClient, db: cachedDb };
}
const config = useRuntimeConfig();
const uri = config.mongoURI;
if (!uri){
throw new Error("Please define the MONGO_URI environment variable inside .env");
}
const client = new MongoClient(uri);
await client.connect();
const db = client.db("sample_restaurants");
cachedClient = client;
cachedDb = db;
console.log("Connected to MongoDB Atlas");
return { client, db };
}

このコードでは、 環境変数に保存されている接続 URI を使用して Atlas クラスターに接続する再利用可能なMongoDBクライアントが作成されます。クライアントは、ニューヨーク市あたりのレストランに関する情報を含む sample_restaurantsデータベースに接続します。

4

NuxサーバールートはAPIリクエストを処理し、データベースと対話します。プロジェクトルートで次のコマンドを実行して、レストラン データを取得するためのサーバールートを作成します。

mkdir -p server/api/restaurants
touch server/api/restaurants/index.get.ts

server/api/restaurants/index.get.tsファイルを開き、次のコードを追加します。

サーバー/api/restaurants/ インデックス.get.ts
import { connectToDatabase } from "~~/server/utils/mongodb";
export default defineEventHandler(async () =>{
const { db } = await connectToDatabase();
const collection = db.collection("restaurants");
const restaurants = await collection
.find({})
.limit(50)
.project({ name: 1, borough: 1, cuisine: 1, grades: 1})
.toArray();
return restaurants.map((doc) => ({
...doc,
_id: doc._id.toString(),
}))
})

このファイルは、restaurantsコレクションをクエリするサーバールートを定義します。最初の 50 レストランのドキュメントを取得し、 JSON応答として返します。

5

プロジェクトルートで次のコマンドを実行して、新しい ルートファイルを作成します。

touch server/api/restaurants/browse.get.ts

server/api/restaurants/browse.get.tsファイルを開き、次のコードを追加します。

サーバー/api/restaurants/browse.get.ts
import { connectToDatabase } from '~~/server/utils/mongodb'
export default defineEventHandler(async () => {
const { db } = await connectToDatabase();
const collection = db.collection("restaurants");
// Filter: Queens borough + name contains "Moon" (case-insensitive)
const query = {
borough: 'Queens',
name: { $regex: 'Moon', $options: 'i' },
}
const restaurants = await collection
.find(query)
.project({ name: 1, borough: 1, cuisine: 1, grades: 1 })
.toArray()
return restaurants.map((doc) => ({
...doc,
_id: doc._id.toString(),
}))
})

このファイルは、名前に Moon という単語が含まれる Queens のレストランを sample_restaurantsデータベースでクエリし、一致するドキュメントをJSON応答として返すサーバールートを定義します。

バックエンドを設定したら、このセクションの手順に従って、アプリケーションの プレゼンテーションレイヤーを設定します。

1

プロジェクトルートで次のコマンドを実行して、グローバル スタイルのメイン CSSファイルを作成します。

mkdir -p app/assets/css
touch app/assets/css/main.css

app/assets/css/main.cssファイルを開き、次のコードを追加します。

アプリ/assets/css/main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

このファイルは、アプリケーションのスタイルを決定するためのユーティリティ クラスを生成する Railwind CSS ディレクティブをインポートします。 tailwind は、カスタム CSS を必要とせずに、レイテンシ、スペース、色、タイプを含む事前に構築されたクラスの包括的なセットを提供します。

2

プロジェクトルートで次のコマンドを実行して、レストラン データを表示するための Vue コンポーネントを作成します。

mkdir -p app/components
touch app/components/RestaurantList.vue

app/components/RestaurantList.vueファイルを開き、次のコードを追加します。

アプリ/components/ResaurantList.vue
<script setup lang="ts">
import { computed } from 'vue'
import { MapPin, Utensils, ChevronRight } from 'lucide-vue-next'
// Type definitions
interface Grade {
grade?: string
score?: number
}
interface Restaurant {
_id: string
name: string
borough?: string
cuisine?: string
grades?: Grade[]
}
// Determine endpoint based on current route
const route = useRoute()
const isBrowse = computed(() => route.path === '/browse')
const endpoint = computed(() =>
isBrowse.value ? '/api/restaurants/browse' : '/api/restaurants'
)
// Fetch data using Nuxt's useFetch composable
// Automatically refetches when endpoint changes
const { data: restaurants } = await useFetch<Restaurant[]>(endpoint, {
watch: [endpoint],
default: () => [],
})
// Dynamic page content
const pageTitle = computed(() =>
isBrowse.value ? 'Hidden Gems in Queens' : 'All Restaurants'
)
const pageSubtitle = computed(() =>
isBrowse.value
? "Filtered by: Borough 'Queens' & Name contains 'Moon'"
: 'Explore our complete directory of local favorites'
)
// Deterministic gradient based on name length
const getGradient = (name: string) => {
const gradients = [
'from-orange-400 to-pink-500',
'from-blue-400 to-indigo-500',
'from-green-400 to-emerald-500',
'from-purple-400 to-fuchsia-500',
]
return gradients[name.length % gradients.length]
}
</script>
<template>
<div class="max-w-6xl mx-auto px-4 py-8">
<!-- Header -->
<div class="mb-8">
<h3 class="text-3xl font-bold text-gray-800">
{{ pageTitle }}
</h3>
<p class="text-gray-500 mt-2">
{{ pageSubtitle }}
</p>
</div>
<!-- Restaurant Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div
v-for="restaurant in restaurants"
:key="restaurant._id"
class="group bg-white rounded-2xl border border-gray-100 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300 overflow-hidden flex flex-col"
>
<!-- Gradient Header -->
<div
:class="[
'h-32 bg-gradient-to-br p-6 flex items-end relative',
getGradient(restaurant.name)
]"
>
<span class="absolute top-4 right-4 bg-white/20 backdrop-blur-md text-white text-xs font-bold px-2 py-1 rounded-full border border-white/30">
Grade {{ restaurant.grades?.[0]?.grade ?? 'N/A' }}
</span>
<h3 class="text-white text-xl font-bold drop-shadow-md line-clamp-2">
{{ restaurant.name }}
</h3>
</div>
<!-- Card Body -->
<div class="p-5 flex-1 flex flex-col">
<div class="flex items-center justify-between mb-4">
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-xs font-medium bg-green-50 text-green-700 border border-green-100">
<Utensils class="w-3 h-3" />
{{ restaurant.cuisine ?? 'Unknown' }}
</span>
<div class="flex items-center text-gray-400 text-xs font-medium">
<MapPin class="w-3 h-3 mr-1" />
{{ restaurant.borough ?? 'Unknown' }}
</div>
</div>
<div class="mt-auto pt-4 border-t border-gray-50 flex items-center justify-between text-sm">
<span class="text-gray-400">
Score: {{ restaurant.grades?.[0]?.score ?? 0 }}
</span>
<button class="text-indigo-600 font-semibold group-hover:underline flex items-center gap-1">
View Menu <ChevronRight class="w-4 h-4" />
</button>
</div>
</div>
</div>
</div>
<!-- Empty State -->
<div v-if="restaurants?.length === 0" class="text-center py-12 text-gray-500">
<p>No restaurants found.</p>
<p class="text-sm mt-2">Check your MongoDB connection and ensure the sample_restaurants database is loaded.</p>
</div>
</div>
</template>

この Vue コンポーネントは Nuxサーバールートからレストラン データを取得し、それを応答性の高いグリッド 配置に表示します。現在のルートに基づいてAPIエンドポイントとページのコンテンツを動的に調整し、すべてのレストランまたはフィルタリングされた結果のいずれかを表示します。

3

プロジェクトルートで次のコマンドを実行して、ナビゲーション バー用の Vue コンポーネントを作成します。

touch app/components/Navbar.vue

app/components/Navbar.vueファイルを開き、次のコードを追加します。

アプリ/components/navbar.vue
<template>
<nav class="flex justify-between items-center mb-6 bg-white shadow-md px-6 py-4 rounded-lg">
<NuxtLink to="/">
<img
alt="MongoDB logo"
class="h-10"
src="https://d3cy9zhslanhfa.cloudfront.net/media/3800C044-6298-4575-A05D5C6B7623EE37/4B45D0EC-3482-4759-82DA37D8EA07D229/webimage-8A27671A-8A53-45DC-89D7BF8537F15A0D.png"
/>
</NuxtLink>
<div class="flex gap-4">
<NuxtLink
to="/"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors"
:class="$route.path === '/'
? 'bg-indigo-100 text-indigo-700'
: 'text-gray-600 hover:bg-gray-100'"
>
All Restaurants
</NuxtLink>
<NuxtLink
to="/browse"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors"
:class="$route.path === '/browse'
? 'bg-indigo-100 text-indigo-700'
: 'text-gray-600 hover:bg-gray-100'"
>
Browse Filtered
</NuxtLink>
</div>
</nav>
</template>

この Vue コンポーネントは、レストランの結果の上にナビゲーションバーをレンダリングし、All RestaurantsFiltered Restaurants リンクを含みます。これらにより、 ルート間を移動できます。

4

プロジェクトルートで次のコマンドを実行して、アプリケーションのインデックスページを作成します。

mkdir -p app/pages
touch app/pages/index.vue

app/pages/index.vueファイルを開き、次のコードを追加します。

アプリ インデックス
<template>
<RestaurantList />
</template>

このファイルには、RestaurantList コンポーネントと Navbar コンポーネントを使用した index.get.tsサーバールートからの結果が表示されます。

5

プロジェクトルートで次のコマンドを実行して、フィルタリングされたレストラン データを表示するための新しい Vue ページを作成します。

touch app/pages/browse.vue

app/pages/browse.vueファイルを開き、次のコードを追加します。

アプリ/pages/browse.vue
<template>
<RestaurantList />
</template>

このファイルには、名前に Moon という単語が含まれる Queens のすべてのレストランが返される、sample_restaurantsデータベースに対するフィルタリングされたクエリの結果が表示されます。ページを構築するには、RestaurantListNavbar コンポーネントも使用します。

6

app/App.vueファイルを開き、その内容を次のコードで置き換えてコンポーネントを接続します。

アプリ/ アプリ.vue
<template>
<div class="w-full p-6 min-h-screen bg-gray-50">
<Navbar />
<NuxtPage />
</div>
</template>
7

続行する前に、ファイルのツリーが以下の構造と完全に一致していることを確認してください。追加のプロジェクトファイルは無視しても問題ありません。

your-project-directory/
├── .env <-- Environment variable file
├── app/
│ ├── app.vue <-- Main application component
│ ├── assets/
│ │ └── css/
│ │ └── main.css <-- Tailwind config
│ ├── components/
│ │ ├── Navbar.vue <-- All restaurants and filtered restaurants links
│ │ └── RestaurantList.vue <-- Container for restaurant data
│ └── pages/
│ ├── browse.vue <-- Filtered restaurants page
│ └── index.vue <-- All restaurants page
├── server/
│ ├── api/
│ │ └── restaurants/
│ │ ├── browse.get.ts <-- Filtered restaurants route
│ │ └── index.get.ts <-- All restaurants route
│ └── utils/
│ └── mongodb.ts <-- MongoDB connection utility
├── nuxt.config.ts <-- Nuxt configuration file
└── package.json

サーバーを起動し、レンダリングされたレストラン データを表示するには、次の手順を実行します。

1

プロジェクトルートで次のコマンドを実行して、開発サーバーを起動します。

npm run dev

成功した場合、コマンドはターミナルに次の情報を出力します。

Nuxt 4.2.2 (with Nitro 2.13.1, Vite 7.3.1 and Vue 3.5.27)
Local: http://localhost:3000/
Network: use --host to expose
Using default Tailwind CSS file
DevTools: press Shift + Option + D in the browser (v3.1.1)
Vite client built in 22ms
Vite server built in 19ms
Nuxt Nitro server built in 247ms
Vite server warmed up in 0ms
Vite client warmed up in 1ms
Connected to MongoDB Atlas
2

ブラウザで http://localhost:3000/ を開きます。最初のランディング ページには、sample_restaurantsデータベース内の最初の 50 レストランが表示されます。

sample_restaurantsデータベース内の最初の 50 レストランを表示するランディングアプリ。
3

フィルタリングされたレストランの結果を表示するには、ナビゲーション バーの Filtered Restaurants リンクをクリックします。 [] ページには、名前に「Moon」という単語が含まれる、Queens のすべてのレストランが表示されます。

名前に MongoDB という単語が含まれるクイーンズのすべてのレストランを表示するフィルタリングされたレストランのページ。

クイック スタート チュートリアルが完了しました。

これらの手順を完了すると、 MongoDBデプロイに接続し、サンプルレストラン データに対してクエリを実行し、その結果をブラウザにレンダリングする Nux と Vueアプリケーションができます。

MongoDB、nux、Vue の使用の詳細については、次のリソースを表示します。

戻る

Meteor と Vue の統合

項目一覧