Skip to content

Conversation

@KirillSto
Copy link
Member

@KirillSto KirillSto commented Aug 29, 2025

https://linear.app/anytype/issue/GO-5800/support-sorting-by-object-relations

Right now any sort upon relations with format tag/status/object/file use object ids to calculate order of objects in subscription.
To support ordering by object names and orderIds of tags following changes were made:

  • dependency service collects infomation on object sorts for subscriptions and triggers subscription reorder in case objects of dependent subscription change its order (orderId/name) and these objects influence sort
  • orderMap is introduced. This struct handles orders of dependent objects and helps to compare objects between each other
  • UpdateOrderMap method is added to database.Order interface. It is triggered on dependant objects change and keeps orders relevant all the time

@KirillSto KirillSto self-assigned this Aug 29, 2025
@KirillSto KirillSto marked this pull request as ready for review September 2, 2025 14:08
@github-actions
Copy link

github-actions bot commented Sep 2, 2025

New Coverage 46.1% of statements
Patch Coverage 86.0% of changed statements (257/299)

Coverage provided by https://github.com/seriousben/go-patch-cover-action

s.skl.Set(e, nil)
}

defer s.diff.reset()
Copy link
Member

Choose a reason for hiding this comment

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

It's a large chunk of complex duplicated code from onChange, let's extract it to function

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved to separate method onSklChange

return
}

entries := s.getActiveEntries()
Copy link
Member

Choose a reason for hiding this comment

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

you have to use all entries, not only the active

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you! Now first we retrieve all entries by iteration over SkipList elements from Front, only then reset Skiplist

return
}

func (ds *dependencyService) enregisterObjectSorts(subId string, sorts []database.SortRequest) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe use verb register? It's much more common

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

return keys
}
for _, sort := range sorts {
keys = append(keys, sort.orderKey())
Copy link
Member

@deff7 deff7 Oct 3, 2025

Choose a reason for hiding this comment

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

You can also use if !slices.Contains here, lo.Uniq is a much heavier operation

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

})
}

if len(sortRelations) != 0 {
Copy link
Member

Choose a reason for hiding this comment

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

len > 0 by code style

Copy link
Member Author

Choose a reason for hiding this comment

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

SortsMap was refactored

depIds = append(depIds, depId)
}
if isSortKey {
if ds.depOrderObjects[depId] == nil {
Copy link
Member

Choose a reason for hiding this comment

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

maybe extract it to a function?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!


type sortsMap map[string][]sortKey // subId -> sortRelationKeys

func (m sortsMap) getSortKey(subId string, key domain.RelationKey) (sortKey, bool) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe add a symmetrical function setSortKeys?

Copy link
Member Author

Choose a reason for hiding this comment

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

SortsMap was refactored. Please take a look, maybe it is not necessary yet

return bundle.RelationKeyName
}

type sortsMap map[string][]sortKey // subId -> sortRelationKeys
Copy link
Member

Choose a reason for hiding this comment

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

Can we benefit from using a map for keys? It seems so

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

@sashagood sashagood requested review from deff7 and removed request for requilence October 7, 2025 10:22
}
}

if hasName {
Copy link
Member

Choose a reason for hiding this comment

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

It will be simpler if you'll add case hasName && hasOrderId here

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

return
s.afterId = ""
if err := s.setBeforeAndAfterElements(); err != nil {
panic(fmt.Errorf("failed to set before and after elements: %w", err))
Copy link
Member

Choose a reason for hiding this comment

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

why to panic here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Replaced with log

return ""
}

var result string
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use strings.Builder here?

Copy link
Member

Choose a reason for hiding this comment

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

Even with strings.Builder this code will be not effective as it could be. Consider using some kind of reusable buffer. Notice that this function is called inside a sorting procedure which has O(n*log n) worst case scenario .

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

Choose a reason for hiding this comment

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

It's better to use shared buffer here

var result string
for _, id := range ids {
if details, ok := m.data[id]; ok {
result += details.GetString(key)
Copy link
Member

Choose a reason for hiding this comment

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

This code implies that arrays [1,2,3] and [2,3,1] are not equal. Does it conform with business rules? Or maybe we must sort sets?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is stated by products to sort by first value, so it works like that already

Value: domain.StringList(idsToSet),
}}})
if err != nil {
log.Errorf("failed to query records to update orders: %v", err)
Copy link
Member

Choose a reason for hiding this comment

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

Consider returning the error and log it on a some upper level. Function will become slightly cleaner

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

RelationKey: key,
Condition: model.BlockContentDataviewFilter_NotEmpty,
}}}, func(details *domain.Details) {
targetIds = append(targetIds, details.GetStringList(key)...)
Copy link
Member

@deff7 deff7 Oct 7, 2025

Choose a reason for hiding this comment

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

Maybe use a map here? Then build a slice from it

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

@KirillSto KirillSto merged commit 91785b1 into develop Oct 14, 2025
5 of 6 checks passed
@KirillSto KirillSto deleted the go-5800-support-sort-by-object-relations branch October 14, 2025 09:13
@github-actions github-actions bot locked and limited conversation to collaborators Oct 14, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants