Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1114: Fix nested sorting key breaks pagination token. #1116

Merged
merged 12 commits into from
Feb 28, 2017

Conversation

n1k0
Copy link
Contributor

@n1k0 n1k0 commented Feb 27, 2017

This is a simplistic attempt at fixing #1114. More tests are probably needed, I'd just like some feedback first.

f=? @Natim @leplatrem @gabisurita

  • Add Changelog entry

@Natim
Copy link
Member

Natim commented Feb 27, 2017

Oh now I understand the bug, so we are supporting filtering on nested fields but not sorting on them. It looks reasonable

@@ -182,6 +182,13 @@ def dict_merge(a, b):
return result


def find_nested_value(dict, path):
if "." not in path:
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately it is not as simple because path can contain dots: See what we did there: https://github.com/Kinto/kinto-admin/blob/62553505e3610831b6119780328dede6c0f784da/src/utils.js#L124-L165

@n1k0
Copy link
Contributor Author

n1k0 commented Feb 27, 2017

@Natim I did my best in 8b0ea7e and 7c8bfbc to come with something better.

# we have our root key, extract the new subpath and recur
subpath = path.replace(root + '.', '', 1)
return find_nested_value(d.get(root), subpath)

Copy link
Contributor

Choose a reason for hiding this comment

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

In storage/memory:apply_filters() and apply_sorting() we had just this:

            left = record
            subfields = f.field.split('.')
            for subfield in subfields:
                if not isinstance(left, dict):
                    break
                left = left.get(subfield)

It might be worth unifying both :) The simpler the better IMO (unless there's a reason hehe)

Copy link
Member

Choose a reason for hiding this comment

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

I would be in favor of using @n1k0 function there too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Really depends if we want to prioritize dotted field key names as my implementation does, or if we don't really care. Probably this is mostly matter of properly documenting the behavior we settle on?

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I'd be in favor of forbidding dots in field names. MongoDB does.

token['last_record'][field] = last_record[field]
last_value = find_nested_value(last_record, field)
if last_value is not None:
token['last_record'][field] = last_value
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if last_value is None ? There is no pagination ? Would that solve #816 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If last_value is None it's most probably because an erroneous sorting field key has been provided. Should we error is such a case, or just ignore it as I did? We could possibly raise a 400 error properly describing the issue to the consumer, which sounds rather good to me. I can work on that if you want.

Copy link
Contributor Author

@n1k0 n1k0 Feb 28, 2017

Choose a reason for hiding this comment

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

Also note that without a JSON schema to validate provided parameters against (in which case all fields are inherently optional), the last record from a chunk might or might not have the field matching the provided key set. In such a case, I don't have any solution in mind, sadly.

def test_find_disambiguated_dotted_path_values(self):
# XXX: To be honest, this is a really scary use case. Probably a
# limitation of the dotted path notation we may want to document.
# At least this test acts as documentation for now.
Copy link
Contributor

Choose a reason for hiding this comment

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

Ahhh that's why... Hmm no strong opinion

@n1k0
Copy link
Contributor Author

n1k0 commented Feb 28, 2017

So I'm gonna go crazy and ask for a review. r=? @Natim @leplatrem

Copy link
Contributor

@leplatrem leplatrem left a comment

Choose a reason for hiding this comment

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

👍

Copy link
Member

@Natim Natim left a comment

Choose a reason for hiding this comment

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

\o/

if not isinstance(left, dict):
break
left = left.get(subfield)
left = find_nested_value(record, f.field)
Copy link
Member

Choose a reason for hiding this comment

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

👍


# we have our root key, extract the new subpath and recur
subpath = path.replace(root + '.', '', 1)
return find_nested_value(d.get(root), subpath)
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we pass default here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The default parameter has None as a default value already, which is consistent with the previous implementation.

Copy link
Contributor Author

@n1k0 n1k0 Feb 28, 2017

Choose a reason for hiding this comment

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

Woops, misread the place where you've added that comment, you're totally right! Edit: #1118

Copy link
Member

Choose a reason for hiding this comment

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

Yes fixed with #1118

# we have our root key, extract the new subpath and recur
subpath = path.replace(root + '.', '', 1)
return find_nested_value(d.get(root), subpath)

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I'd be in favor of forbidding dots in field names. MongoDB does.

@Natim Natim merged commit 6915291 into master Feb 28, 2017
@Natim Natim deleted the 1114-fix-nested-key-pagination-token branch February 28, 2017 16:53
n1k0 added a commit that referenced this pull request Feb 28, 2017
Post #1116 fix: ensure default propagation in find_nested_value.
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.

4 participants