Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding new MongoMP application #76

Merged
merged 2 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions apps/mongo-mp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules

# next.js
/.next/
/out/

# production
/build

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
299 changes: 299 additions & 0 deletions apps/mongo-mp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
# MongoMP - MongoDB Music Platform

![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
![Version](https://img.shields.io/badge/version-1.0.0-blue)
![License](https://img.shields.io/badge/license-MIT-green)

![MognoMP](./mongomp-ui.png)
MongoMP is a cutting-edge music streaming platform that leverages the power of MongoDB and Next.js to provide a personalized and immersive listening experience.

## Features

- 🎵 Extensive music library with various genres
- 🤖 AI-powered song recommendations using MongoDB's vector search
- This approach enables the system to identify songs with similar musical characteristics by comparing their vector embeddings to the user's centroid vector, leading to more accurate and personalized recommendations. [Learn more about centroid calculation](#centroid-calculation).
- 🔍 Advanced search functionality
- 📊 Real-time play count and last played tracking
- 📱 Responsive design for seamless use across devices
- 🎨 Customizable user profiles
- 📜 Playlist creation and management
- 🔐 Secure user authentication with JWT

## Tech Stack

- **Frontend**: Next.js 14 with App Router
- **Backend**: Node.js with Next.js API Routes
- **Database**: MongoDB
- **Authentication**: JWT (JSON Web Tokens)
- **Styling**: Tailwind CSS and shadcn/ui components


## centroid-calculation

The centroid calculation mechanism works by automatically computing and updating a user's musical taste profile based on their liked songs. Here's how it works:

### Overview
When a user likes or unlikes songs (updating their `likes` array), a MongoDB Trigger automatically calculates the centroid (average) of the musical embeddings for all liked songs.

### Technical Implementation
1. **Trigger Activation**: Monitors changes to user documents' `likes` array
2. **Data Processing Pipeline**:
- Matches all liked songs in the songs collection
- Unwinds the musical embeddings arrays
- Groups and averages embeddings by dimension
- Sorts to maintain dimensional order
- Combines into a single centroid vector

### Code Example
```javascript
exports = async function(changeEvent) {
const docId = changeEvent.documentKey._id;
const serviceName = "<CLUSTER_NAME>";
const db = context.services.get(serviceName).db("mongomp");
const usersCollection = db.collection("users");
const songsCollection = db.collection("songs");

try {
// Get the updated user document
const userDoc = changeEvent.fullDocument;

if (!userDoc.likes || userDoc.likes.length === 0) {
console.log("No likes found for user:", docId);
return;
}

const pipeline = [
// Match liked songs
{
$match: {
_id: { $in: userDoc.likes }
}
},
// Unwind the embeddings array to work with individual elements
{
$unwind: {
path: "$music_embeddings",
includeArrayIndex: "dimension_index"
}
},
// Group by dimension index to calculate averages
{
$group: {
_id: "$dimension_index",
avg_value: { $avg: "$music_embeddings" }
}
},
// Sort by dimension index to maintain order
{
$sort: {
_id: 1
}
},
// Project to get just the averaged values in array form
{
$group: {
_id: null,
liked_embeddings: {
$push: "$avg_value"
}
}
}
];

const aggregationResult = await songsCollection.aggregate(pipeline).toArray();

if (!aggregationResult || aggregationResult.length === 0) {
console.log("No embeddings calculated");
return;
}

// Update user document with averaged embeddings
const updateResult = await usersCollection.updateOne(
{ _id: docId },
{
$set: {
liked_embeddings: aggregationResult[0].liked_embeddings
}
}
);

console.log("Updated user embeddings:", {
userId: docId,
numberOfLikes: userDoc.likes.length,
embeddingsDimensions: aggregationResult[0].liked_embeddings.length,
updateResult: updateResult
});

} catch (err) {
console.log("Error processing embeddings:", err.message);
console.log("Full error:", JSON.stringify(err));
}
};
```

The resulting centroid vector becomes the user's musical taste profile, stored in `liked_embeddings`, enabling personalized song recommendations through vector similarity search.

## Getting Started

### Prerequisites

- Node.js (v14 or later)
- MongoDB (v4.4 or later)
- npm or yarn

### Installation

1. Clone the repository:
```bash
git clone <repository_url>
```

2. Navigate to the project directory:
```bash
cd mongo-mp
```

3. Install dependencies:
```bash
npm install
```
or
```bash
yarn install
```

### Setting up the Database

1. Ensure your MongoDB instance is running and accessible.

2. Create a `.env.local` file in the root directory of the project and add your MongoDB connection string:
```
MONGODB_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret
```

3. Run the database seeding script to populate your database with sample data and create indexes:
```bash
npm run seed
```
or
```bash
yarn seed
```
This script is located in `scripts/seed-db.js` and will create sample users, songs, and needed indexes.


### Running the Application

1. Start the development server:
```
npm run dev
```
or
```bash
yarn dev
```

2. Your application should now be running on `http://localhost:3000`


## Installation and Deployment

### Building Locally

1. After following the installation steps, build the project:
```
npm run build
```


2. Start the production server:
```
npm start
```

3. Your application should now be running on `http://localhost:3000`

### Deployment

MongoMP can be easily deployed to Vercel:

1. Push your code to a GitHub repository.
2. Go to [Vercel](https://vercel.com) and sign up or log in.
3. Click on "New Project" and import your GitHub repository.
4. Configure your environment variables (MONGODB_URI and JWT_SECRET).
5. Click "Deploy" and wait for the build to complete.

Your MongoMP instance will now be live on a Vercel URL!

## Project Structure

Here's an overview of the MongoMP project structure:

```
mongo-mp/
├── app/
│ ├── api/
│ │ ├── auth/
│ │ │ ├── login/
│ │ │ ├── logout/
│ │ │ ├── register/
│ │ │ └── user/
│ │ ├── playlists/
│ │ ├── songs/
│ │ └── user/
│ ├── admin/
│ │ └── users/
│ ├── library/
│ ├── login/
│ ├── profile/
│ ├── register/
│ ├── search/
│ ├── home-content.tsx
│ ├── layout.tsx
│ └── page.tsx
├── components/
│ ├── ui/
│ ├── bottom-nav.tsx
│ ├── code-block.tsx
│ ├── info-tooltip.tsx
│ ├── library-content.tsx
│ ├── navbar.tsx
│ ├── notification.tsx
│ ├── playing-song-popup.tsx
│ ├── playlist-player.tsx
│ ├── RetroEqualizer.tsx
│ ├── search-bar.tsx
│ ├── song-card.tsx
│ ├── song-list.tsx
│ ├── suggested-songs.tsx
│ ├── tag.tsx
│ └── user-menu.tsx
├── contexts/
│ └── UserContext.tsx
├── hooks/
│ ├── useAudio.ts
│ └── useUser.ts
├── lib/
│ ├── mock-data.ts
│ ├── mock-users.ts
│ ├── mongodb.ts
│ └── utils.ts
├── public/
│ └── placeholder.svg
├── scripts/
│ └── seed-db.js
├── types/
│ ├── playlist.ts
│ └── song.ts
├── .env.local
├── .gitignore
├── next.config.js
├── package.json
├── README.md
├── tailwind.config.js
└── tsconfig.json
```

This structure shows the main directories and files in the MongoMP project. The `app/` directory contains the Next.js 14 App Router structure, with API routes and page components. The `components/` directory holds reusable React components, and `lib/` contains utility functions and database connection logic.

16 changes: 16 additions & 0 deletions apps/mongo-mp/app/admin/users/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Metadata } from 'next'
import { UserManagement } from '@/components/user-management'

export const metadata: Metadata = {
title: 'User Management - MongoMP Admin',
description: 'Manage users of the MongoMP music streaming platform',
}

export default function UsersPage() {
return (
<div className="container mx-auto py-10">
<UserManagement />
</div>
)
}

Loading
Loading