The proximity search fetched its anchor through get(), which omits vectors
by default, then handed a zero-length vector to the index — every
find({ near }) refused with a dimension mismatch, for every caller. Found
by the Rust planner's first-contact pins comparing outcomes with and
without the planner on a refused shape. The anchor is now fetched with its
vector, and an anchor that has none refuses by name — a proximity search
around an unvectored row has no meaning and must not fail inside the index.
Pinned in tests/integration/find-near.test.ts.
48 lines
2.1 KiB
TypeScript
48 lines
2.1 KiB
TypeScript
/**
|
|
* @module tests/integration/find-near
|
|
* @description find({ near }) searches around the anchor's OWN vector (10.4.10).
|
|
*
|
|
* The proximity search fetched its anchor without vectors and fed a
|
|
* zero-length vector to the index — every near() refused with a dimension
|
|
* mismatch, for every caller. Found by the Rust planner's first-contact pins
|
|
* (the planner declines `near`; the pin compared outcomes with and without
|
|
* it). Now the anchor is fetched with its vector, and an anchor without one
|
|
* refuses by name instead of failing inside the index.
|
|
*/
|
|
import { describe, it, expect, beforeAll } from 'vitest'
|
|
import { Brainy } from '../../src/brainy'
|
|
import { NounType } from '../../src/types/graphTypes'
|
|
import { v5 } from '../../src/universal/uuid'
|
|
import { generateTestVector } from '../helpers/test-factory'
|
|
|
|
describe('find({ near }) uses the anchor vector', () => {
|
|
let brain: Brainy<any>
|
|
const anchorVector = generateTestVector()
|
|
|
|
beforeAll(async () => {
|
|
brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' } })
|
|
await brain.init()
|
|
await brain.add({ id: 'anchor', data: 'anchor row', type: NounType.Thing, vector: anchorVector })
|
|
// A twin with the identical vector and a far row.
|
|
await brain.add({ id: 'twin', data: 'twin row', type: NounType.Thing, vector: [...anchorVector] })
|
|
await brain.add({ id: 'far', data: 'far row', type: NounType.Thing, vector: generateTestVector() })
|
|
})
|
|
|
|
it('returns the anchor\'s neighbours by its own vector', async () => {
|
|
const results = await brain.find({ near: { id: 'anchor' }, limit: 3 })
|
|
expect(results.length).toBeGreaterThan(0)
|
|
const ids = results.map((r) => r.entity.id)
|
|
expect(ids).toContain(v5('twin'))
|
|
})
|
|
|
|
it('refuses by name when the anchor has no vector', async () => {
|
|
await brain.add({
|
|
id: 'unvectored',
|
|
data: 'no vector here',
|
|
type: NounType.Thing,
|
|
deferEmbedding: true
|
|
})
|
|
;(brain as any).kickEmbedWorker = () => {}
|
|
await expect(brain.find({ near: { id: 'unvectored' }, limit: 3 })).rejects.toThrow(/has no vector to search around/)
|
|
})
|
|
})
|