Skip to content

feat(iterator): add DocIterator for full collection traversal#597

Open
YongqiYin wants to merge 1 commit into
alibaba:mainfrom
YongqiYin:feat/doc-iterator
Open

feat(iterator): add DocIterator for full collection traversal#597
YongqiYin wants to merge 1 commit into
alibaba:mainfrom
YongqiYin:feat/doc-iterator

Conversation

@YongqiYin

Copy link
Copy Markdown
Collaborator

Add streaming full-collection traversal across C++/C/Python:

  • C++: Collection::CreateIterator + DocIterator (isolated Flush+snapshot scan, ConcatenatingReader across segments, FilteringReader for deletes, batch-prefetched vectors)
  • C API: zvec_collection_create_iterator/next/close + iterator options
  • Python: collection.iter_docs() generator (constant memory)
  • Tests: C++ (unit/integration/concurrency/perf), C API, Python

Relates to #380

Copilot AI review requested due to automatic review settings July 16, 2026 12:53

Copilot AI 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.

Pull request overview

This PR introduces a full-collection document iterator (“DocIterator”) across the C++ core, C API, and Python bindings to enable streaming traversal/export without relying on large topk queries (relates to #380).

Changes:

  • Add C++ Collection::CreateIterator() and DocIterator with snapshot isolation, segment concatenation, and delete filtering.
  • Expose the iterator via the C API (zvec_collection_create_iterator/next/close) and Python (Collection.iter_docs() generator).
  • Add C++/C/Python tests covering basic iteration, delete filtering, field selection, and concurrency/isolation.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/db/iterator_test.cc New C++ unit/integration/concurrency/perf tests for full traversal.
tests/c/c_api_test.c Adds C API iterator tests and option handling coverage.
src/include/zvec/db/options.h Introduces IteratorOptions (output_fields/include_vector).
src/include/zvec/db/doc_iterator.h Public C++ DocIterator interface.
src/include/zvec/db/collection.h Adds Collection::CreateIterator() API.
src/include/zvec/c_api.h Adds public C iterator and iterator-options API.
src/db/index/segment/filtering_reader.h New Arrow reader wrapper to filter deleted docs.
src/db/index/segment/concatenating_reader.h New Arrow reader to concatenate readers across segments.
src/db/doc_iterator.cc Implements row-by-row Doc materialization + optional vector prefetch.
src/db/doc_iterator_internal.h Internal DocIterator::Impl definition (lifetime ordering, caches).
src/db/collection.cc Implements iterator creation, snapshot scan, and reader chain construction.
src/binding/python/model/python_collection.cc Exposes _DocIterator + Collection.CreateIterator() to Python.
src/binding/python/include/python_collection.h Declares bind_iterator() hook.
src/binding/c/c_api.cc Implements iterator options + iterator handles for the C API.
python/zvec/model/collection.py Adds Collection.iter_docs() streaming generator.
python/tests/test_iter_docs.py New Python tests for iterator behavior and isolation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/db/iterator_test.cc
Comment on lines +15 to +18
#include <atomic>
#include <chrono>
#include <thread>
#include <gtest/gtest.h>
Comment thread src/db/collection.cc Outdated

Result<DocIterator::Ptr> CollectionImpl::CreateIterator(
const IteratorOptions &options) {
CHECK_COLLECTION_READONLY_RETURN_STATUS_EXPECTED;
Comment thread src/db/doc_iterator.cc
Comment on lines +201 to +205
auto uid_array =
std::dynamic_pointer_cast<arrow::StringArray>(batch.column(uid_col));
if (uid_array) {
doc->set_pk(uid_array->GetScalar(row).ValueOrDie()->ToString());
}
Comment thread src/db/doc_iterator.cc
Comment on lines +229 to +233
auto str_array = std::dynamic_pointer_cast<arrow::StringArray>(array);
if (str_array) {
doc->set(field->name(),
str_array->GetScalar(row).ValueOrDie()->ToString());
}
Comment thread src/binding/c/c_api.cc
Comment on lines +6914 to +6919
auto *ptr = reinterpret_cast<zvec::IteratorOptions *>(options);
// NULL output_fields means "return all fields" (nullopt).
if (output_fields == nullptr || count == 0) {
ptr->output_fields_ = std::nullopt;
return ZVEC_OK;
}
Comment thread python/zvec/model/collection.py Outdated
Comment on lines +398 to +402
iterator = self._obj.CreateIterator(output_fields, include_vector)
for core_doc in iterator:
py_doc = convert_to_py_doc(core_doc, self.schema)
if py_doc is not None:
yield py_doc
Comment thread tests/c/c_api_test.c Outdated
Comment on lines +5897 to +5902
size_t ok_count = 0, err_count = 0;
zvec_collection_insert(collection, (const zvec_doc_t **)docs, 1, &ok_count,
&err_count);
zvec_doc_destroy(doc);
}
zvec_collection_flush(collection);
Comment thread tests/c/c_api_test.c Outdated
const char *fields[] = {"id"};
err = zvec_iterator_options_set_output_fields(opts, fields, 1);
TEST_ASSERT(err == ZVEC_OK);
zvec_iterator_options_set_include_vector(opts, false);
@YongqiYin
YongqiYin force-pushed the feat/doc-iterator branch from b596564 to 4aca7cb Compare July 16, 2026 13:01
@YongqiYin

Copy link
Copy Markdown
Collaborator Author

@copilot resolve the merge conflicts in this pull request

@CLAassistant

CLAassistant commented Jul 16, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Copilot AI 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.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Comment thread src/db/collection.cc
Comment on lines +2201 to +2205
// Create DocIterator, keeping segments + delete_store alive
auto impl = std::make_unique<DocIterator::Impl>();
impl->reader = reader_result.value();
impl->schema = schema_;
impl->segments = std::move(segments);
Comment thread src/db/doc_iterator.cc
Comment on lines +129 to +136
void DocIterator::Close() {
if (impl_) {
impl_->closed = true;
impl_->reader.reset();
impl_->current_batch.reset();
impl_->vector_cache_.clear();
}
}
Comment thread src/db/doc_iterator.cc
Comment on lines +175 to +183
uint32_t seg_doc_id =
static_cast<uint32_t>(ga->Value(i) - min_doc_id);
auto fr = indexer->Fetch(seg_doc_id);
if (fr.has_value()) {
bufs.push_back(std::move(fr.value()));
} else {
bufs.emplace_back();
}
}
@YongqiYin
YongqiYin force-pushed the feat/doc-iterator branch from feef1d7 to 96273fc Compare July 17, 2026 04:49
Add streaming full-collection traversal across C++/C/Python:
- C++: Collection::CreateIterator + DocIterator (isolated Flush+snapshot
  scan, ConcatenatingReader across segments, FilteringReader for deletes,
  batch-prefetched vectors)
- C API: zvec_collection_create_iterator/next/close + iterator options
- Python: collection.iter_docs() generator (constant memory)
- Tests: C++ (unit/integration/concurrency/perf), C API, Python

Relates to alibaba#380
@YongqiYin
YongqiYin force-pushed the feat/doc-iterator branch from 96273fc to 4f542e0 Compare July 17, 2026 06:04
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.

3 participants