Store
nlql.store —— Store 接口、StoreCaps 能力描述,以及内置的 LocalStore(基于 numpy 的精确检索)。各后端实现 Store 接口;引擎将过滤等操作尽量交给后端的原生能力处理,其余在内存中完成。
store
Store protocol and the built-in LocalStore (numpy flat index).
__all__
module-attribute
__all__ = ['Store', 'StoreCaps', 'LocalStore', 'matches_filter']
Store
Bases: Protocol
The storage + retrieval interface the executor runs against.
upsert
upsert(units: Sequence[Unit]) -> None
源代码位于: src/nlql/store/base.py
| def upsert(self, units: Sequence[Unit]) -> None: ...
|
add_documents
add_documents(documents: Iterable[Document]) -> None
源代码位于: src/nlql/store/base.py
| def add_documents(self, documents: Iterable[Document]) -> None: ...
|
get_document
get_document(doc_id: str) -> Document | None
源代码位于: src/nlql/store/base.py
| def get_document(self, doc_id: str) -> Document | None: ...
|
ann_search
ann_search(vector: ndarray, k: int | None = None, *, filter: Expr | None = None) -> list[tuple[Unit, float]]
Return up to k (unit, cosine) pairs matching filter, best first.
源代码位于: src/nlql/store/base.py
| def ann_search(
self,
vector: np.ndarray,
k: int | None = None,
*,
filter: Expr | None = None,
) -> list[tuple[Unit, float]]:
"""Return up to ``k`` ``(unit, cosine)`` pairs matching ``filter``, best first."""
...
|
scan
scan(filter: Expr | None = None) -> list[Unit]
Return all units matching filter (non-vector path).
源代码位于: src/nlql/store/base.py
| def scan(self, filter: Expr | None = None) -> list[Unit]:
"""Return all units matching ``filter`` (non-vector path)."""
...
|
all_units
all_units() -> list[Unit]
源代码位于: src/nlql/store/base.py
| def all_units(self) -> list[Unit]: ...
|
neighbors
neighbors(doc_id: str, ordinal: int, window: int) -> list[Unit]
Units of the same document within ±window ordinals, ordinal-ordered.
源代码位于: src/nlql/store/base.py
| def neighbors(self, doc_id: str, ordinal: int, window: int) -> list[Unit]:
"""Units of the same document within ``±window`` ordinals, ordinal-ordered."""
...
|
capabilities
源代码位于: src/nlql/store/base.py
| def capabilities(self) -> StoreCaps: ...
|
__len__
源代码位于: src/nlql/store/base.py
| def __len__(self) -> int: ...
|
StoreCaps
dataclass
StoreCaps(name: str = 'local', vector_search: bool = True, exact: bool = True, metadata_pushdown: bool = False, text_pushdown: bool = False)
What a store can do natively.
name
class-attribute
instance-attribute
vector_search
class-attribute
instance-attribute
vector_search: bool = True
exact
class-attribute
instance-attribute
metadata_pushdown: bool = False
text_pushdown
class-attribute
instance-attribute
text_pushdown: bool = False
LocalStore
Bases: BaseUnitStore
Process-local unit store with an exact flat vector index.
源代码位于: src/nlql/store/local.py
| def __init__(self) -> None:
super().__init__()
self._ids: list[str] = []
self._matrix: np.ndarray = np.empty((0, 0), dtype=np.float32)
self._columns = MetadataColumns()
|
ann_search
ann_search(vector: ndarray, k: int | None = None, *, filter: Expr | None = None) -> list[tuple[Unit, float]]
源代码位于: src/nlql/store/local.py
| def ann_search(
self,
vector: np.ndarray,
k: int | None = None,
*,
filter: Expr | None = None,
) -> list[tuple[Unit, float]]:
self._ensure_index()
n = self._matrix.shape[0]
if n == 0:
return []
query = normalize(vector)
if query.shape[0] != self._matrix.shape[1]:
raise NLQLExecutionError(
f"query dim {query.shape[0]} != index dim {self._matrix.shape[1]}"
)
scores = self._matrix @ query # cosine, since both sides are unit-normalized
if filter is not None:
candidate_idx = np.nonzero(self._columns.mask(filter))[0]
else:
candidate_idx = np.arange(n)
if candidate_idx.size == 0:
return []
cand_scores = scores[candidate_idx]
order = np.argsort(-cand_scores)
if k is not None:
order = order[:k]
return [
(self._units[self._ids[int(candidate_idx[o])]], float(cand_scores[o])) for o in order
]
|
scan
scan(filter: Expr | None = None) -> list[Unit]
源代码位于: src/nlql/store/local.py
| def scan(self, filter: Expr | None = None) -> list[Unit]:
if filter is None:
return list(self._units.values())
self._ensure_index()
keep = self._columns.mask(filter)
return [self._units[self._ids[i]] for i in np.nonzero(keep)[0]]
|
capabilities
源代码位于: src/nlql/store/local.py
| def capabilities(self) -> StoreCaps:
return StoreCaps(name="local", vector_search=True, exact=True, metadata_pushdown=True)
|
matches_filter
matches_filter(expr: Expr | None, metadata: dict[str, Any]) -> bool
Whether metadata satisfies a pushed metadata filter (None matches all).
源代码位于: src/nlql/store/filter.py
| def matches_filter(expr: Expr | None, metadata: dict[str, Any]) -> bool:
"""Whether ``metadata`` satisfies a pushed metadata filter (``None`` matches all)."""
if expr is None:
return True
if isinstance(expr, Compare):
return compare_values(
expr.op, _operand(expr.left, metadata), _operand(expr.right, metadata)
)
if isinstance(expr, And):
return all(matches_filter(o, metadata) for o in expr.operands)
if isinstance(expr, Or):
return any(matches_filter(o, metadata) for o in expr.operands)
if isinstance(expr, Not):
return not matches_filter(expr.operand, metadata)
return False
|
后端适配器
以下适配器实现 Store 接口,需安装对应 extras:
| 适配器 |
模块 |
extras |
LocalStore |
nlql.store.local |
内置 |
FaissStore |
nlql.store.faiss_store |
nlql[faiss] |
HnswStore |
nlql.store.hnsw_store |
nlql[hnsw] |
QdrantStore |
nlql.store.qdrant_store |
nlql[qdrant] |
ChromaStore |
nlql.store.chroma_store |
nlql[chroma] |
PgVectorStore |
nlql.store.pgvector_store |
nlql[pgvector] |
各后端的能力差异(向量检索类型、元数据与全文过滤)见 混合后端。