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

Resolve #64 (Allow to discover available fields for a document) #65

Merged
merged 6 commits into from
Jul 11, 2022
Merged

Resolve #64 (Allow to discover available fields for a document) #65

merged 6 commits into from
Jul 11, 2022

Conversation

fbilhaut
Copy link

@fbilhaut fbilhaut commented Jun 29, 2022

@ostafen, just wondering if what I assume are "reserved" fields like "__id" should be included by GetKeys(). Currently they are, but I think they might preferably not. In such case, is it clearly documented that field names starting with "_" are supposed to be reserved ? Let me know

document.go Show resolved Hide resolved
document.go Outdated Show resolved Hide resolved
document.go Outdated
return getKeysRecursive(doc.fields, "")
}

func getKeysRecursive(fields map[string]interface{}, prefix string) []string {
Copy link
Owner

Choose a reason for hiding this comment

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

I think this can be implemented without the need of the extra prefix parameter, by concatenating key + "." to each element of result

Copy link
Author

Choose a reason for hiding this comment

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

I think communicating this information to sub-calls is mandatory in such a recursive implementation. I might be wrong, but I'm afraid this is "mathematically" unavoidable. Otherwise level n call has no way to know about the parent nodes that have been visited during level 0..n-1 calls.

That being said, I made it basic and recursive for the sake of simplicity, and because the depth of the traversal will always be marginal which doesn't justify the overhaul of an iterative version. But of course we could make it iterative and avoid an extra parameter.

BTW I moved it to utils.go, although it could be made more generic (specify separator, avoid having to pass the empty prefix at first call, etc.)

Copy link
Owner

@ostafen ostafen Jul 1, 2022

Choose a reason for hiding this comment

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

I think communicating this information to sub-calls is mandatory in such a recursive implementation. I might be wrong, but I'm afraid this is "mathematically" unavoidable. Otherwise level n call has no way to know about the parent nodes that have been visited during level 0..n-1 calls.

Communicating this information is mandatory in your implementation, because you want each subcall to return the "full" field name, also considering its parent. However, when you solve a recursive sub-problem, you should avoid to embed information of the whole problem inside the sub-problem.

Give a look at this:

func getKeys(fields map[string]interface{}) []string {
	result := []string{}
	for key, value := range fields {
		subMap, isMap := value.(map[string]interface{})
		if isMap {
			subFields := getKeys(subMap)
			for _, subKey := range subFields {
				result = append(result, key+"."+subKey)
			}
		} else {
			result = append(result, key)
		}
	}
	return result
}

Please, simply call the function getKeys(), also.

Copy link
Author

Choose a reason for hiding this comment

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

Hi Stefano,

It works, but this is pretty ineffective to re-scan each sub-map. Transferring the prefix just takes a bit on the stack but has no additional computational time. That being said, that's your project, so you're the boss :) But to me performance is key in such a lib.

As for the name, you already have a getKeys() function in compare.go with the same signature. This one doesn't deep-traverse the map, and sorts the result. I'm not fond of the "Recursive" prefix as well but...

Copy link
Owner

@ostafen ostafen Jul 1, 2022

Choose a reason for hiding this comment

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

If we were to be so concerned on the performance of this, I think we would't go for a recursive implementation at all, so it is a bit overkilled to me thinking at optimization at this level. Moreover, we are not talking of a function affecting query execution time, so it's fine to trade some cpu cycle for simplicity.

Regarding the function name, you could call it geAllKeys().

Copy link
Author

Choose a reason for hiding this comment

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

OK Stefano, let's not enter a battle of opinions about this. That's just not my way of designing code and algorithms, but I'll push a last commit this way to close the subject. (BTW recursive implementations are not ineffective per se, but that's another story.)

Copy link
Owner

@ostafen ostafen left a comment

Choose a reason for hiding this comment

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

Hi, @fbilhaut, thank you for contributing. I requested you some changes. I think that special attributes, such as "_id" should be included

db_test.go Show resolved Hide resolved
Copy link
Owner

@ostafen ostafen left a comment

Choose a reason for hiding this comment

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

Thank you! Just one more thing, and we're done

@ostafen ostafen merged commit afc10d3 into ostafen:main Jul 11, 2022
@ostafen
Copy link
Owner

ostafen commented Jul 11, 2022

Thank you!

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