-
-
Notifications
You must be signed in to change notification settings - Fork 55
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
Conversation
document.go
Outdated
return getKeysRecursive(doc.fields, "") | ||
} | ||
|
||
func getKeysRecursive(fields map[string]interface{}, prefix string) []string { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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()
.
There was a problem hiding this comment.
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.)
There was a problem hiding this 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
There was a problem hiding this 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
Thank you! |
@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