[MongoDB] Vector Search
MongoDB๋ ๋ฒกํฐ ๊ฒ์ ๊ธฐ๋ฅ์ ๊ณต์์ ์ผ๋ก ์ง์ํ๋ค.
7.* ๋ฒ์ ์์๋ ์ ์ฉ ํด๋ผ์ฐ๋์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํด์ ํฌ์ง์ ์ด ์ง์ง ์ ๋งคํ๋๋ฐ, 8.*์์๋ ๋ฒกํฐ ๊ฒ์ ๊ธฐ๋ฅ์ด ์คํ์์ค ๋ฒ์ ์๋ ํฌํจ๋์ด์๋ค.
์ ํ ๋ฐ ํธํ์ฑ
MongoDB Cloud๋ฅผ ์ด๋ค๋ฉด 7~8 ๋ฒ์ ์์ ๋ชจ๋ ์ฌ์ฉํ ์ ์๊ณ , ์คํ์์ค ๋ฒ์ ์ผ๋ก ์ฌ์ฉํ๋ค๋ฉด 8 ๋ฒ์ ์ ์ฌ์ฉํด์ผ๋ง ํ๋ค. Linux๋ฉด ๋์ถฉ ๋ค ๋๋ค.
https://www.mongodb.com/ko-kr/docs/atlas/atlas-vector-search/compatibility-limitations/
ํ ์คํธ ๋ฐ์ดํฐ ์ธํ
๋จผ์ ๋ฐ์ดํฐ๋ถํฐ ๊น์๋ณด์. ๋ฒกํฐ ์์ฒด๋ ๊ทธ๋ฅ ์ค์์ ๋ฐฐ์ด๋ก ๋ฃ์ผ๋ฉด ๋๋ค.
db.products.insertMany([
{
name: "๋นจ๊ฐ ์ํผ์ค",
category: "๋๋ ์ค",
description: "์ฌ๋ฆ์ฉ ํ๋ก๋ด ์ํผ์ค",
embedding: [0.1, 0.8, 0.3, 0.5, 0.2],
},
{
name: "์ฒญ๋ฐ์ง",
category: "๋ฐ์ง",
description: "์ฌ๋ฆผํ ๋ฐ๋ ํฌ์ธ ",
embedding: [0.9, 0.1, 0.7, 0.2, 0.4],
},
{
name: "ํฐ ๋ธ๋ผ์ฐ์ค",
category: "์์",
description: "์คํผ์ค๋ฃฉ ์์ค๋ฃจ ๋ธ๋ผ์ฐ์ค",
embedding: [0.3, 0.6, 0.1, 0.8, 0.5],
},
{
name: "ํ๋ฆฌ์ธ ์ค์ปคํธ",
category: "์ค์ปคํธ",
description: "๋ฏธ๋ ๊ธธ์ด ์ฃผ๋ฆ ์ค์ปคํธ",
embedding: [0.2, 0.7, 0.4, 0.6, 0.3],
},
]);

๋ฒกํฐ ์ธ๋ฑ์ค ์์ฑ
๊ทธ๋ผ ์ด์ ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค์ด๋ณด์.
๋ค์ ์คํฌ๋ฆฝํธ๋ ์นดํ
๊ณ ๋ฆฌ์ ๋ํ ๋ฉํ๋ฐ์ดํฐ ์ธ๋ฑ์ค๊ฐ ํฌํจ๋ ๋ฒกํฐ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ค.
// 2. Vector Search ์ธ๋ฑ์ค ์์ฑ
db.products.createSearchIndex(
"vector_index", // ์ด๋ฆ
"vectorSearch",
{
fields: [
// ๋ฒกํฐ ์ธ๋ฑ์ค
{
type: "vector",
path: "embedding",
numDimensions: 5,
similarity: "cosine",
},
// ํํฐ๋ง์ ์ํ ์นดํ
๊ณ ๋ฆฌ ํ๋
{
type: "filter",
path: "category",
},
],
}
);
์ฐจ์์ 5, ์ ์ฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฝ์ฌ์ธ์ผ๋ก ๋ฃ์๋ค.
์ ์ฌ๋ ํ์
์ euclidean, cosine, dotProduct๊ฐ ์ง์๋๋ค.
๋น์ฐํ HNSW ๊ธฐ๋ฐ์ ๊ทผ์ฌ์น ๊ฒ์ ์ธ๋ฑ์ค๊ณ ,
๋์์ด๋ ๋ด๋ถ ๊ตฌํ ๋ฐฉ์์ Elasticsearch/Opensearch๊ณผ ๊ฑฐ์ ๊ฐ๋ค.
์ธ๋ถ์ ์ธ ์ต์
์ ๋ค์ ๋ฌธ์๋ฅผ ์ฐธ์กฐํ๋ค.
https://www.mongodb.com/ko-kr/docs/atlas/atlas-vector-search/vector-search-type/?deployment-type=atlas&embedding=byo&interface=driver&language=python#mongodb-vector-search-index-fields
๋ฒกํฐ ๊ฒ์ ์ฟผ๋ฆฌ
๋ฒกํฐ ๊ฒ์์ ์ผ๋ฐ find๋ก๋ ๋ถ๊ฐ๋ฅํ๊ณ , aggregate์ ํ ์ ๋ก๋ง ์ง์๋๋ค.
๋ค์๊ณผ ๊ฐ์ด $vectorSearch ์ ์ ๋ฃ์ด์ ๊ฒ์์ ๋๋ฆฌ๋ฉด ๋๋ ๊ฒ์ด๋ค.
db.products.aggregate([
{
$vectorSearch: {
index: "vector_index",
path: "embedding",
queryVector: [0.2, 0.7, 0.3, 0.6, 0.4], // ๊ฒ์ ์ฟผ๋ฆฌ ๋ฒกํฐ
numCandidates: 10, // ํ๋ณด๊ตฐ (Candidates)
limit: 3, // ์ต์ข
๋ฐํ ์ (K)
},
},
{
$project: {
_id: 0,
name: 1,
category: 1,
description: 1,
score: { $meta: "vectorSearchScore" }, // ์ ์ฌ๋ ์ ์
},
},
]);
๊ทธ๋ผ ์ด๋ฐ ์์ผ๋ก, ์ ์ฌ๋ ์ ์์ ๋๋ถ์ด ์ ์ฌ๋๋ก ์ ๋ ฌ๋ ๊ฐ์ ๋ฐ์์ฌ ์ ์๋ค.
filter ์ ์ ์ฌ์ฉํด์ ๋ฒกํฐ ๊ฒ์์ ์ ์ฉํ ํํฐ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
์ ๊ธฐ์ ๋ค์ด๊ฐ๋ ํํฐ ์์ ํ๋๋, ๋ฒกํฐ ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค๋ ๋ฃ์ด์ค filter ์ปฌ๋ผ๋ง ๋ฃ์ ์ ์๋ค. ์๋๋ฉด ์๋ฌ๊ฐ ๋๋ค.
pre-filtering์ ์ค์บ ๋ฐฉ์์ Elasticsearch/Opensearch์ ๊ฑฐ์ ๋น์ทํ๋ค. ํํฐ๋ง์ผ๋ก ์ธํด ๋ง์ ํญ๋ชฉ์ด ๊ฑธ๋ฌ์ ธ์ HNSW ์ค์บ ๋ฒ์ ๋ด์ ์ถฉ๋ถํ K๊ฐ ์๋ค๋ฉด, ์ถฉ๋ถํ K๊ฐ ๋์ฌ๋๊น์ง HNSW ์ค์บ์ ๋ฐ๋ณตํ๋ ๋ฐฉ์์ด๋ค.
์ฐธ์กฐ
https://www.mongodb.com/ko-kr/docs/atlas/atlas-vector-search/vector-search-overview/
https://www.mongodb.com/ko-kr/docs/atlas/atlas-vector-search/tutorials/vector-search-quick-start/?deployment-type=atlas&embedding=byo&interface=driver&language=python
https://www.mongodb.com/company/blog/product-release-announcements/supercharge-self-managed-apps-search-vector-search-capabilities
https://www.mongodb.com/ko-kr/docs/atlas/atlas-vector-search/vector-search-type/?deployment-type=atlas&embedding=byo&interface=driver&language=python