Skip to content

[Feat] Flyway 마이그레이션 + embedding_models seed - #42

Merged
kangcheolung merged 3 commits into
developfrom
feature/41
Jul 21, 2026
Merged

[Feat] Flyway 마이그레이션 + embedding_models seed#42
kangcheolung merged 3 commits into
developfrom
feature/41

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 21, 2026

Copy link
Copy Markdown
Member

🔍 작업 내용

✨ 상세 설명

Flyway V32 — vector 컬럼 변환 및 HNSW 인덱스

  • embeddings.vector, search_queries.query_vector TEXT → vector(1024) 타입 변환
  • HNSW 인덱스 추가 (코사인 거리 기반 ANN 검색 가속)

db/seed 정비

  • 기존 MOCK 모델 seed 제거 → R__seed_bge_m3_embedding_model.sql로 교체 (BAAI/bge-m3, 1024차원,
    model_version 1.0)

VectorType — 커스텀 Hibernate UserType

  • global/common/type/VectorType.java: pgvector의 vector(1024) (Types#OTHER)를 float[]로 매핑
  • 외부 라이브러리 없이 JDBC PGobject만으로 구현, 스키마 검증 통과 확인

엔티티 수정

  • Embedding.vector, SearchQuery.queryVector: Stringfloat[] + @Type(VectorType.class)
  • build.gradle: postgresql 의존성 runtimeOnlyimplementation (PGobject 컴파일 타임 사용)

🛠️추후 리팩토링 및 고도화 계획

📸 스크린샷 (선택)

💬 리뷰 요구사항

  • VectorType 외부 라이브러리 없이 직접 구현한 방식이 적절한지
  • R__ seed 파일의 ON CONFLICT 처리 누락된 케이스 없는지

Summary by CodeRabbit

  • 새 기능

    • 벡터 데이터를 PostgreSQL vector(1024) 형식으로 저장하고 조회할 수 있습니다.
    • 코사인 거리 기반 HNSW 인덱스를 적용해 벡터 검색 성능을 지원합니다.
    • BAAI/bge-m3 임베딩 모델과 개발용 테스트 데이터가 자동으로 준비됩니다.
  • 문서

    • 벡터 검색 데이터베이스 인프라 구축 절차와 설계 내용을 추가했습니다.

kangcheolung and others added 3 commits July 21, 2026 17:03
- V32: embeddings.vector, search_queries.query_vector TEXT → vector(1024) 변환 및 HNSW 인덱스 추가
- R__seed_bge_m3_embedding_model: mock 모델 seed를 실제 BAAI/bge-m3(HUGGINGFACE) seed로 교체
- R__seed_test_fixtures: 벡터 검색 동작 확인용 개발 더미 데이터 추가 (문서 2개, 청크 4개, 임베딩 4개)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- VectorType: pgvector의 vector(1024) SQL 타입을 float[]로 매핑하는 커스텀 Hibernate UserType
- Embedding.vector, SearchQuery.queryVector: String → float[] + @type(VectorType.class)로 교체
- postgresql 의존성을 runtimeOnly → implementation으로 변경 (PGobject 컴파일 타임 사용)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

pgvector 기반으로 벡터 컬럼과 Java float[] 매핑을 전환하고, HNSW 인덱스·임베딩 모델 seed·개발용 테스트 픽스처를 추가했습니다. PostgreSQL JDBC 의존성은 컴파일 시점에도 사용할 수 있도록 변경했으며, 관련 설계 문서를 작성했습니다.

Changes

벡터 검색 DB 인프라

Layer / File(s) Summary
pgvector 스키마와 Java 매핑
src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql, src/main/java/com/opensource/docgrid/global/common/type/VectorType.java, src/main/java/com/opensource/docgrid/domain/{embedding,search}/entity/*.java
embeddings.vectorsearch_queries.query_vectorvector(1024)로 변경하고 HNSW 인덱스를 추가했습니다. VectorType은 PostgreSQL vector와 Java float[] 간 읽기·쓰기 및 복제 처리를 담당하며 두 엔티티에 적용됩니다.
임베딩 모델과 테스트 픽스처 seed
src/main/resources/db/seed/R__seed_bge_m3_embedding_model.sql, src/main/resources/db/seed/R__seed_test_fixtures.sql, src/main/resources/db/seed/R__seed_mock_embedding_model.sql
BAAI/bge-m3 모델 seed를 추가하고, 문서·버전·청크·1024차원 임베딩으로 구성된 개발용 픽스처를 멱등 방식으로 삽입합니다. 기존 mock 모델 seed는 제거되었습니다.
빌드 설정과 설계 문서
build.gradle, docs/design/kangcheolung-#41-vector-search-db-infrastructure.md
PostgreSQL JDBC 의존성 범위를 runtimeOnly에서 implementation으로 변경하고, 마이그레이션·seed·VectorType·엔티티 매핑 설계를 문서화했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • DocGrid/backend#11: embedding_models 제약과 mock seed를 다뤄 현재 모델 seed 변경과 직접 연결됩니다.

Suggested labels: ✨ Feature, 📃 Docs

Suggested reviewers: gimini-3

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 Flyway 마이그레이션과 embedding_models 시드 교체라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 필수 섹션이 모두 포함되어 있고 작업 내용, 향후 계획, 리뷰 요구사항도 구체적으로 적혀 있습니다.
Linked Issues check ✅ Passed [#41] TEXT→vector 전환, HNSW 인덱스, bge-m3 seed 교체, 버전 명시, 개발용 픽스처 추가가 모두 반영되었습니다.
Out of Scope Changes check ✅ Passed 문서 추가와 build.gradle 변경은 벡터 매핑/seed 교체를 지원하는 범위로 보이며, 명백한 무관 변경은 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/41

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql (1)

10-10: 🩺 Stability & Availability | 🔵 Trivial

대용량 테이블 인덱스 생성 시 쓰기 잠금(Write Lock)을 고려하세요.

테이블의 데이터가 많을 경우 CREATE INDEX는 인덱스 생성이 완료될 때까지 테이블의 쓰기(Insert/Update/Delete) 작업을 차단합니다. 만약 데이터 규모가 큰 운영 환경을 가정한다면 가동 시간 확보를 위해 CONCURRENTLY 옵션 사용을 고려해볼 수 있습니다. (단, Flyway에서 CONCURRENTLY를 사용하려면 해당 스크립트가 트랜잭션 외부에서 실행되도록 별도로 분리 설정되어야 합니다.)

As per coding guidelines, do not make assumptions silently; state assumptions, surface uncertainty, and present multiple interpretations when applicable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql`
at line 10, Update the HNSW index creation statement to use concurrent creation
for the large embeddings table, and configure this migration to run outside
Flyway’s transaction as required by CREATE INDEX CONCURRENTLY. Keep the existing
index definition and vector_cosine_ops operator class unchanged.

Source: Coding guidelines

src/main/java/com/opensource/docgrid/global/common/type/VectorType.java (1)

43-48: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

문자열 파싱 예외 처리를 강화하세요.

데이터베이스의 벡터 문자열 포맷이 훼손되었거나 빈 텍스트일 경우, 현재 로직은 StringIndexOutOfBoundsException 혹은 NumberFormatException 런타임 에러를 발생시킬 수 있습니다. 시스템 안정성을 위해 방어적 검증 로직을 추가하고 명시적인 SQLException으로 래핑하는 것을 권장합니다.

As per path instructions, SOLID 원칙, 스프링 어노테이션, 의존성 주입 패턴, 예외 처리에 중점을 둔다.

🛠️ Proposed fix to improve exception handling
-        String[] parts = value.substring(1, value.length() - 1).split(",");
-        float[] result = new float[parts.length];
-        for (int i = 0; i < parts.length; i++) {
-            result[i] = Float.parseFloat(parts[i].trim());
-        }
-        return result;
+        if (value.length() < 2 || !value.startsWith("[") || !value.endsWith("]")) {
+            throw new SQLException("Invalid vector string format: " + value);
+        }
+        String inner = value.substring(1, value.length() - 1).trim();
+        if (inner.isEmpty()) {
+            return new float[0];
+        }
+        String[] parts = inner.split(",");
+        float[] result = new float[parts.length];
+        try {
+            for (int i = 0; i < parts.length; i++) {
+                result[i] = Float.parseFloat(parts[i].trim());
+            }
+        } catch (NumberFormatException e) {
+            throw new SQLException("Failed to parse vector elements", e);
+        }
+        return result;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/opensource/docgrid/global/common/type/VectorType.java`
around lines 43 - 48, Update the string parsing logic in VectorType to validate
null/empty input and the expected bracketed vector format before substring and
numeric conversion. Catch StringIndexOutOfBoundsException and
NumberFormatException, then wrap parsing failures in an explicit SQLException
while preserving successful parsing behavior.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/kangcheolung-`#41-vector-search-db-infrastructure.md:
- Around line 16-17: Update the embeddings.vector migration to preserve existing
vectors by converting the column in place with ALTER COLUMN ... TYPE
vector(1024) USING ..., or add a temporary column, backfill it, then enforce NOT
NULL before replacing the original. Remove the DROP COLUMN and direct NOT NULL
ADD COLUMN sequence so existing rows are retained and the migration succeeds
without a default.

In `@src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql`:
- Around line 3-4: Replace the destructive DROP COLUMN/ADD COLUMN sequence in
migration V32 with an ALTER COLUMN TYPE conversion using a USING expression,
matching the existing search_queries migration pattern, so embeddings.vector
data is preserved while becoming vector(1024). Ensure the conversion handles the
column’s current type explicitly and retains the NOT NULL constraint.

---

Nitpick comments:
In `@src/main/java/com/opensource/docgrid/global/common/type/VectorType.java`:
- Around line 43-48: Update the string parsing logic in VectorType to validate
null/empty input and the expected bracketed vector format before substring and
numeric conversion. Catch StringIndexOutOfBoundsException and
NumberFormatException, then wrap parsing failures in an explicit SQLException
while preserving successful parsing behavior.

In `@src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql`:
- Line 10: Update the HNSW index creation statement to use concurrent creation
for the large embeddings table, and configure this migration to run outside
Flyway’s transaction as required by CREATE INDEX CONCURRENTLY. Keep the existing
index definition and vector_cosine_ops operator class unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a6c4963e-7fb1-4b05-8208-966c7b2ff3c8

📥 Commits

Reviewing files that changed from the base of the PR and between f42be75 and 8d8cb2b.

📒 Files selected for processing (9)
  • build.gradle
  • docs/design/kangcheolung-#41-vector-search-db-infrastructure.md
  • src/main/java/com/opensource/docgrid/domain/embedding/entity/Embedding.java
  • src/main/java/com/opensource/docgrid/domain/search/entity/SearchQuery.java
  • src/main/java/com/opensource/docgrid/global/common/type/VectorType.java
  • src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql
  • src/main/resources/db/seed/R__seed_bge_m3_embedding_model.sql
  • src/main/resources/db/seed/R__seed_mock_embedding_model.sql
  • src/main/resources/db/seed/R__seed_test_fixtures.sql
💤 Files with no reviewable changes (1)
  • src/main/resources/db/seed/R__seed_mock_embedding_model.sql

Comment on lines +16 to +17
ALTER TABLE embeddings DROP COLUMN vector;
ALTER TABLE embeddings ADD COLUMN vector vector(1024) NOT NULL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find relevant files and inspect the doc plus migration references.
printf '\n== FILE LIST ==\n'
git ls-files | rg 'docs/design/kangcheolung-#41-vector-search-db-infrastructure\.md|V32|embeddings|vector'

printf '\n== DOC CONTEXT ==\n'
doc='docs/design/kangcheolung-#41-vector-search-db-infrastructure.md'
if [ -f "$doc" ]; then
  nl -ba "$doc" | sed -n '1,80p'
fi

printf '\n== SEARCH FOR V32 / EMBEDDINGS / VECTOR ==\n'
rg -n --hidden -S 'V32|embeddings|vector\(1024\)|ALTER TABLE embeddings|DROP COLUMN vector|ADD COLUMN vector' .

Repository: DocGrid/backend

Length of output: 429


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# If a V32 migration exists, print its path and relevant lines around vector changes.
rg -n --hidden -S 'CREATE TABLE embeddings|ALTER TABLE embeddings|vector\(1024\)|DROP COLUMN vector|ADD COLUMN vector|USING .*vector' . \
  | sed -n '1,200p'

Repository: DocGrid/backend

Length of output: 3592


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Narrow search for migration filenames and any vector-related schema definitions.
fd -a -t f 'V32|vector|embedding|embeddings' . | sed -n '1,200p'

Repository: DocGrid/backend

Length of output: 1063


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in src/main/resources/db/migration/V16__create_embeddings.sql \
         src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql \
         src/main/java/com/opensource/docgrid/domain/embedding/entity/Embedding.java \
         src/main/java/com/opensource/docgrid/domain/search/entity/SearchQuery.java
do
  printf '\n===== %s =====\n' "$f"
  if [ -f "$f" ]; then
    sed -n '1,220p' "$f"
  else
    echo "missing"
  fi
done

Repository: DocGrid/backend

Length of output: 11505


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -S 'insert into embeddings|into embeddings|save\(.*Embedding|new Embedding|`@Entity`\s*.*Embedding|embedding' \
  src/main/resources src/main/java | sed -n '1,240p'

Repository: DocGrid/backend

Length of output: 34404


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== MIGRATION REFERENCES ==\n'
rg -n -S 'embeddings' src/main/resources/db/migration src/main/resources/db/seed | sed -n '1,240p'

printf '\n== ENTITY/REPOSITORY REFERENCES ==\n'
rg -n -S 'EmbeddingRepository|EmbeddingService|saveAll?\(|save\(.*Embedding|new Embedding|Embeddings' src/main/java | sed -n '1,240p'

Repository: DocGrid/backend

Length of output: 3016


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in src/main/resources/db/migration/V16__create_embeddings.sql \
         src/main/resources/db/seed/R__seed_test_fixtures.sql \
         src/main/resources/db/seed/R__seed_bge_m3_embedding_model.sql
do
  printf '\n===== %s =====\n' "$f"
  if [ -f "$f" ]; then
    python3 - <<'PY' "$f"
import sys, pathlib
p = pathlib.Path(sys.argv[1])
for i, line in enumerate(p.read_text().splitlines(), 1):
    if i <= 200:
        print(f"{i:4d}: {line}")
PY
  else
    echo "missing"
  fi
done

Repository: DocGrid/backend

Length of output: 9978


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' src/main/resources/db/migration/V16__create_embeddings.sql

Repository: DocGrid/backend

Length of output: 1621


V32__convert_vector_columns_to_pgvector.sql는 drop/add 대신 변환으로 바꾸세요.
embeddings.vector를 삭제했다가 vector(1024) NOT NULL로 다시 추가하면 기존 행의 벡터가 유실되고, 기본값 없는 NOT NULL 추가도 실패합니다. ALTER COLUMN ... TYPE vector(1024) USING ...로 변환하거나 새 컬럼 추가 → 백필 → NOT NULL 적용 순서로 처리해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/kangcheolung-`#41-vector-search-db-infrastructure.md around lines
16 - 17, Update the embeddings.vector migration to preserve existing vectors by
converting the column in place with ALTER COLUMN ... TYPE vector(1024) USING
..., or add a temporary column, backfill it, then enforce NOT NULL before
replacing the original. Remove the DROP COLUMN and direct NOT NULL ADD COLUMN
sequence so existing rows are retained and the migration succeeds without a
default.

Comment on lines +3 to +4
ALTER TABLE embeddings DROP COLUMN vector;
ALTER TABLE embeddings ADD COLUMN vector vector(1024) NOT NULL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

실 데이터 유실 위험이 있는 DROP COLUMN 대신 타입 캐스팅을 사용하세요.

개발 환경에만 적용된다는 가정이 있으나, 해당 Flyway 마이그레이션 스크립트가 운영 및 스테이징 환경에 배포될 경우 embeddings 테이블의 기존 벡터 데이터가 영구적으로 삭제됩니다. search_queries 테이블(7행)과 동일하게 USING 절을 통한 타입 변환을 권장합니다.

As per coding guidelines, do not make assumptions silently; state assumptions, surface uncertainty, and present multiple interpretations when applicable.

🛡️ Proposed fix to preserve data
-ALTER TABLE embeddings DROP COLUMN vector;
-ALTER TABLE embeddings ADD COLUMN vector vector(1024) NOT NULL;
+ALTER TABLE embeddings ALTER COLUMN vector TYPE vector(1024) USING vector::vector;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ALTER TABLE embeddings DROP COLUMN vector;
ALTER TABLE embeddings ADD COLUMN vector vector(1024) NOT NULL;
ALTER TABLE embeddings ALTER COLUMN vector TYPE vector(1024) USING vector::vector;
🧰 Tools
🪛 Squawk (2.59.0)

[warning] 3-3: Dropping a column may break existing clients.

(ban-drop-column)


[warning] 4-4: Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required. Make the field nullable or add a non-VOLATILE DEFAULT

(adding-required-field)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql`
around lines 3 - 4, Replace the destructive DROP COLUMN/ADD COLUMN sequence in
migration V32 with an ALTER COLUMN TYPE conversion using a USING expression,
matching the existing search_queries migration pattern, so embeddings.vector
data is preserved while becoming vector(1024). Ensure the conversion handles the
column’s current type explicitly and retains the NOT NULL constraint.

Source: Coding guidelines

@kangcheolung
kangcheolung merged commit 86b1ecc into develop Jul 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] Flyway 마이그레이션 + embedding_models seed

1 participant