Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

feat: Secondary index reader#829

Merged
garrensmith merged 6 commits intomainfrom
secondary-reader
Mar 1, 2023
Merged

feat: Secondary index reader#829
garrensmith merged 6 commits intomainfrom
secondary-reader

Conversation

@garrensmith
Copy link
Copy Markdown
Contributor

Describe your changes

Secondary Index reader that queries from the secondary index.

How best to test these changes

Issue ticket number and link

@reviewpad reviewpad bot added the large label Feb 16, 2023
@garrensmith garrensmith added debug image This PR will generate a debug image and removed large labels Feb 16, 2023
@reviewpad reviewpad bot added the large label Feb 16, 2023
}

// TODO: I think this might need to be changed, we should only support search on the search endpoint
if options.filter.None() || !options.filter.IsIndexed() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we still support search as a reader option or should it only be part of the search API?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The reader option is internal to us but to answer your question, yes we need to support it till we backfill the secondary indexes and point the read queries to start using secondary indexes. Then it will only be Search.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Created issue #869 for this

Comment thread query/filter/key_builder.go
Comment thread server/config/options.go Outdated
SecondaryIndex: SecondaryIndexConfig{
ReadEnabled: false,
WriteEnabled: false,
ReadEnabled: true,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

let's not enable it in the config yet.

Comment thread server/services/v1/database/query_runner.go Outdated
Comment thread server/services/v1/database/query_runner.go Outdated
}

// TODO: I think this might need to be changed, we should only support search on the search endpoint
if options.filter.None() || !options.filter.IsIndexed() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The reader option is internal to us but to answer your question, yes we need to support it till we backfill the secondary indexes and point the read queries to start using secondary indexes. Then it will only be Search.

eqPlan, err := eqKeyBuilder.Build(queryFilters, coll.QueryableFields)
if err == nil {
for _, plan := range eqPlan {
if indexedDataType(plan) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if it is equality and the plan is not index type what is the behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This can happen if the field is a []byte. Then the plan is ignored and we look for another eq plan or move to range plans

if len(repeatedFields) == 0 {
// nothing found or a gap
return nil, errors.InvalidArgument("filters doesn't contains primary key fields")
if s.matchAll {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So this will go away once we move to secondary indexes because then it doesn't matter if we are able to build the primary key from the filter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes that will be awesome. I've created #870 to remember to do this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

great

Comment thread query/filter/key_builder.go
}

// Prefer a RANGE scan which should read back less keys than a FULLRANGE
// for _, queryType := range []filter.QueryPlanType{filter.RANGE, filter.FULLRANGE} {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove it if not needed.

Comment thread server/services/v1/database/secondary_index_reader.go Outdated
// Range Key Composer will generate a range key set on the user defined keys
// It will set the KeyQuery to `FullRange` if the start or end key is not defined in the query
// if there is a defined start and end key for a range then `Range` is set.
type RangeKeyComposer[F fieldable] struct {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For this diff, the structure is good. But if we think about it, we just need two high level abstractions here,

  • NewQueryableKeyBuilder(composer, primaryKey) [will be used by insert/replace only]
  • NewQueryableKeyBuilder(): This will internally use eq/range composer to build plans i.e. equality as well as range. The reason being once we don't rely on the search store then either the plan is formed or we need to fall back to full table scan, there will be no other option. Then Read/Update/Delete can rely directly on it. This means we need to add something to the QueryPlan so that caller knows whether the keys are for primary or secondary indexes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes I like it. We can definitely move to that direction once search and secondary are ready.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

sg

@garrensmith garrensmith changed the title [WIP]Secondary reader Secondary reader Feb 23, 2023
Copy link
Copy Markdown
Contributor Author

@garrensmith garrensmith left a comment

Choose a reason for hiding this comment

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

Thanks for the feedback. I've made the changes.

}

// NewPrimaryKeyEQBuild returns a KeyBuilder for use with schema.Field to build a primary key query plan.
func NewPrimaryKeyEqBuilder(keyEncodingFunc KeyEncodingFunc) *KeyBuilder[*schema.Field] {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think we could do that a little later once secondary indexes are deployed. At the moment we have to pass some extra params if it is a PrimaryKey versus secondary.

Comment thread query/filter/key_builder.go
if len(repeatedFields) == 0 {
// nothing found or a gap
return nil, errors.InvalidArgument("filters doesn't contains primary key fields")
if s.matchAll {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes that will be awesome. I've created #870 to remember to do this.

// Range Key Composer will generate a range key set on the user defined keys
// It will set the KeyQuery to `FullRange` if the start or end key is not defined in the query
// if there is a defined start and end key for a range then `Range` is set.
type RangeKeyComposer[F fieldable] struct {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes I like it. We can definitely move to that direction once search and secondary are ready.

eqPlan, err := eqKeyBuilder.Build(queryFilters, coll.QueryableFields)
if err == nil {
for _, plan := range eqPlan {
if indexedDataType(plan) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This can happen if the field is a []byte. Then the plan is ignored and we look for another eq plan or move to range plans

Comment thread query/filter/filter.go
}
collation = value.NewCollationFrom(apiCollation)

if buildForSecondaryIndex && collation.IsCaseInsensitive() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So we won't be supporting case-insensitive queries on secondary indexes fields?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can support it in the in-memory filter part but not part of what we use to build the range keys. Or at least I can't think of a way of making that work.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sure, we can figure it out iteratively.

@garrensmith garrensmith force-pushed the secondary-reader branch 3 times, most recently from 0896d17 to 74869e7 Compare March 1, 2023 05:54
himank
himank previously approved these changes Mar 1, 2023
@himank himank changed the title Secondary reader feat: Secondary index reader Mar 1, 2023
@garrensmith garrensmith merged commit 40f2fdd into main Mar 1, 2023
@garrensmith garrensmith deleted the secondary-reader branch March 1, 2023 10:39
@tigrisdata-argocd-bot
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 1.0.0-beta.46 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

debug image This PR will generate a debug image large released on @beta

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants