-
Notifications
You must be signed in to change notification settings - Fork 598
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
Get Unique Entity Key String #625
Comments
That's a good question. What you're looking at is really just a (mostly) base64 encoded version of the So for example: var path = ['Person', 1, 'Playlist', 1234];
var encodedPath = btoa(JSON.stringify(path)); // "WyJQZXJzb24iLDEsIlBsYXlsaXN0IiwxMjM0XQ=="
var decodedPath = JSON.parse(atob(encodedPath)); // ["Person",1,"Playlist",1234] @ryanseys @stephenplusplus : Do you think it's worthwhile to add this method to the Key class so we don't make people implement it themselves? |
(For reference, here is the code that deals with the |
Hmm, trying to see the use case for this. I think we'd suggest that gcloud-node be used primarily driven by API calls, and I don't see that this information (base64'd reference protobuf stuff) is directly accessible through the API, rather you'd have to do extraneous work to put it in that format or manually extract it from the web view, so it's likely an edge case we won't directly support. @jgeewax does it sound like I am understanding you correctly given what you've said above? |
I can understand if this is an edge case, but in general I have worked with the datastore in both Java and Python, but it looks like the return values in both of these languages when trying to convert them to json come out a lot different than gcloud is there a reason why in Java and Python the format is a bit flatter and the keys don't include paths (see to_dict() method for example in Python)? I was thinking this might be why the guid keys were being used to keep the json a bit flatter, maybe? Also I tried running the code above on a guid key and it doesn't seem to come out right, is that more pseudo code or should it work on a full key guid string? Thanks for all the help! |
@ryanseys If we think of this use case as ... "Make it easy for people to pass around key=" and retrieve it on a request, I think it'd be useful to have a method that serializes a string in something that is URL safe... That is, in express... var express = require('express');
var gcloud = require('gcloud')({ projectId: 'my-project' });
var app = express();
var dataset = gcloud.datastore.dataset();
// GET /?key=WyJQZXJzb24iLDEsIlBsYXlsaXN0IiwxMjM0XQ==
app.get('/', function(req, res){
dataset.get(dataset.key({encodedValue: req.query.key}, function(err, entity) {
res.redirect('/otherPath?key=' + entity.key.encodedValue());
});
});
app.listen(3000); @shaunc869 What problems are you seeing with that same code...? Can you be more specific? I'm just using Javascript to JSON stringify a list and base-64 encode it... nothing gcloud-specific here. |
@jgeewax I agree, that helper method would be awesome. I am trying to copy and past the entity key guid string from the datastore entity editor on the developers console and then base64 decode it and I am not getting the full path for some reason. |
@shaunc869 That code wasn't a way of decoding from the exact same format as the entity editor -- it was just an example demonstrating how we might go about this. You could certainly figure it out assuming it's using the same encoding style that NDB does (NDB's decoding logic is here: https://code.google.com/p/appengine-ndb-experiment/source/browse/ndb/key.py#803). |
Ah that makes sense, I will try my best with that, but I generally wait for much smarter developers like you to figure this stuff out. I will take a crack at the ndb stuff and see what I can come up. If this was to be implemented here would you use the same algorithm as ndb, I was assuming this was some kind of standard? |
I believe (I could be wrong) but all that's happening is base64 encoding with a couple find/replace characters (-'s and /'s?) and then chopping off trailing ='s. |
I copied the exact code from that ndb code and ran it against the app engine console string and it does not come as a readable path. What am I doing wrong? |
To help you, I'd need to see the exact code you're talking about... @shaunc869 |
I grabbed the ndb code: def _DecodeUrlSafe(urlsafe):
"""Decode a url-safe base64-encoded string.
This returns the decoded string.
"""
if not isinstance(urlsafe, basestring):
raise TypeError('urlsafe must be a string; received %r' % urlsafe)
if isinstance(urlsafe, unicode):
urlsafe = urlsafe.encode('utf8')
mod = len(urlsafe) % 4
if mod:
urlsafe += '=' * (4 - mod)
# This is 3-4x faster than urlsafe_b64decode()
return base64.b64decode(urlsafe.replace('-', '+').replace('_', '/')) And if you try to run this you don't get a path like I would expect, I must be missing something? |
It's not returning the path -- it's returning the binary of a Reference protobuf. What I wrote above:
So you'd need to then create the protobuf object ... and then read the path property from that... :( It doesn't look like it'd be fun code to write or use (and seems like it's totally overkill when a path suffices) so it's really really unlikely that gcloud-node would go that route when "coming up with a serializable version" of a key. (We'd likely go the route of just serializing the path, since that's unique...) Is there some specific reason that you need to emulate the exact same encoding of the key from the Datastore UI? |
My current situation is I have an app engine Python app that I want to move to node so I am trying to emulate the same ajax methods I have on my python webapp2 app, which has a getter for all the entity types and returns a nice flat JSON model that I can manipulate on the client side and then save back. This is probably related, but just now when I went to save back the data I sent the following: {
key: {
path: [
"PhoneNumber",
5313141421375488
]
},
data: {
company_id: {
path: [
"Company",
4791049928048640
]
},
sid: "PN07d490d21f4f803c82bcadad342348",
phone_number: "+13601234333",
call_recording_enabled: false,
date_added: "2015-04-26T22:10:48.000Z",
date_updated: "2015-04-26T22:19:52.818Z",
name: "Main Phone Number",
form_id: {
path: [
"Form",
473767298046333336
]
},
twiml: [ ]
}
} Normally I would expect this to update the datastore and save a reference to both the Form object and Company object in the datastore like it does in Python, but instead I see:
and
the datastore viewer isn't resolving this to the appropriate objects in the datastore like it would had I converted the JSON to a Python object via: phone_number = PhoneNumber(**number_json)
phone_number.put() Thanks for all the help! |
Hm.. I think this kind of stuff might be better answered over on Stack Overflow as it's getting pretty specific about your app and less so about gcloud-node. I'm going to leave this issue open, with the goal that we expose some way of nicely serializing a key's path so that users don't have to come up with their own ways of doing it, but I don't think I'm going to be as much help on your specific case (but SO is probably going to be much more useful)! |
Sounds good I will move it over there, thanks! On Mon, May 25, 2015 at 11:04 AM, JJ Geewax [email protected]
Shaun |
Just a ping on the main issue here (which is "let's provide some URL-encodable option for the Key"): Couldn't someone wanting to pass a key around simply do: key = dataset.key({
namespace: 'my-namespace',
path: ['Kind', 'asdf', 'ChildKind', 1234]
});
var keyForURI = encodeURIComponent(JSON.stringify(key)); ? Or does that not work...? |
Yeah, that would produce: encoded:
decoded:
That's what I would do! |
Is it worth providing a |
I think it should be figured out by the user, as we're not doing anything unique. Just stringifying and uri encoding. The encoding can be skipped in most libraries: var postKey = dataset.key(['Post', 'post1']);
require('request').get({
uri: 'http://localhost/',
qs: {
key: JSON.stringify(postKey) // sending a key object as a string. JSON.stringify is perfect
}
});
// GET /saveKey?key=%7B%22path%22%3A%5B%22Post%22%2C%22post1%22%5D%7D |
I might have missed something but the referenced articles do not provide any progress on the matter and the suggested solution from above - using atob doesn't work for me. Are there any news regarding the ability to query datastore using the URL-safe key in Node? |
hey, for me on datastore, i found out that the results from an insertion matches something like const key = {
kind: 'projects',
path: ['projects', id],
id,
} so the id is a number matching something like meaning that you can pass this around in your app and then when you need to fetch it you construct the object in the way datastore.get expects it to be ie to fetch a project const project = async ({ id }, { datastore }) => {
const entity = await datastore.get({
kind: 'projects',
path: ['projects', id],
id,
});
return Object.assign(entity.pop(), {
id,
});
}; will return the data as it in on the data store row. when creating the entity on data store, you can get the id like const create = async ({ project }, { datastore }) => {
const key = datastore.key('projects');
await datastore.save({
key,
data: project,
});
const { id } = key;
return Object.assign(project, {
id,
});
}; returns an object with an id you can use around in url's |
* feat!: Update library to use Node 12 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
* feat!: Update library to use Node 12 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
* feat!: Update library to use Node 12 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
This PR was generated using Autosynth. 🌈 Synth log will be available here: https://source.cloud.google.com/results/invocations/2812cef8-9404-4275-bb51-8c6dafc1bc6f/targets - [ ] To automatically regenerate this PR, check this box. PiperOrigin-RevId: 361273630 Source-Link: googleapis/googleapis@5477122
- [ ] Regenerate this pull request now. PiperOrigin-RevId: 470911839 Source-Link: googleapis/googleapis@3527566 Source-Link: googleapis/googleapis-gen@f16a1d2 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZjE2YTFkMjI0ZjAwYTYzMGVhNDNkNmE5YTFhMzFmNTY2ZjQ1Y2RlYSJ9 feat: accept google-gax instance as a parameter Please see the documentation of the client constructor for details. PiperOrigin-RevId: 470332808 Source-Link: googleapis/googleapis@d4a2367 Source-Link: googleapis/googleapis-gen@e97a1ac Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZTk3YTFhYzIwNGVhZDRmZTczNDFmOTFlNzJkYjdjNmFjNjAxNjM0MSJ9
* build!: Update library to use Node 12 Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [mocha](https://mochajs.org/) ([source](https://togithub.com/mochajs/mocha)) | devDependencies | major | [`^7.0.0` -> `^8.0.0`](https://renovatebot.com/diffs/npm/mocha/7.2.0/8.0.1) | --- ### Release Notes <details> <summary>mochajs/mocha</summary> ### [`v8.0.1`](https://togithub.com/mochajs/mocha/blob/master/CHANGELOG.md#​801--2020-06-10) [Compare Source](https://togithub.com/mochajs/mocha/compare/v8.0.0...v8.0.1) The obligatory patch after a major. #### 🐛 Fixes - [#​4328](https://togithub.com/mochajs/mocha/issues/4328): Fix `--parallel` when combined with `--watch` ([**@​boneskull**](https://togithub.com/boneskull)) ### [`v8.0.0`](https://togithub.com/mochajs/mocha/blob/master/CHANGELOG.md#​800--2020-06-10) [Compare Source](https://togithub.com/mochajs/mocha/compare/v7.2.0...v8.0.0) In this major release, Mocha adds the ability to _run tests in parallel_. Better late than never! Please note the **breaking changes** detailed below. Let's welcome [**@​giltayar**](https://togithub.com/giltayar) and [**@​nicojs**](https://togithub.com/nicojs) to the maintenance team! #### 💥 Breaking Changes - [#​4164](https://togithub.com/mochajs/mocha/issues/4164): **Mocha v8.0.0 now requires Node.js v10.0.0 or newer.** Mocha no longer supports the Node.js v8.x line ("Carbon"), which entered End-of-Life at the end of 2019 ([**@​UlisesGascon**](https://togithub.com/UlisesGascon)) - [#​4175](https://togithub.com/mochajs/mocha/issues/4175): Having been deprecated with a warning since v7.0.0, **`mocha.opts` is no longer supported** ([**@​juergba**](https://togithub.com/juergba)) ✨ **WORKAROUND:** Replace `mocha.opts` with a [configuration file](https://mochajs.org/#configuring-mocha-nodejs). - [#​4260](https://togithub.com/mochajs/mocha/issues/4260): Remove `enableTimeout()` (`this.enableTimeout()`) from the context object ([**@​craigtaub**](https://togithub.com/craigtaub)) ✨ **WORKAROUND:** Replace usage of `this.enableTimeout(false)` in your tests with `this.timeout(0)`. - [#​4315](https://togithub.com/mochajs/mocha/issues/4315): The `spec` option no longer supports a comma-delimited list of files ([**@​juergba**](https://togithub.com/juergba)) ✨ **WORKAROUND**: Use an array instead (e.g., `"spec": "foo.js,bar.js"` becomes `"spec": ["foo.js", "bar.js"]`). - [#​4309](https://togithub.com/mochajs/mocha/issues/4309): Drop support for Node.js v13.x line, which is now End-of-Life ([**@​juergba**](https://togithub.com/juergba)) - [#​4282](https://togithub.com/mochajs/mocha/issues/4282): `--forbid-only` will throw an error even if exclusive tests are avoided via `--grep` or other means ([**@​arvidOtt**](https://togithub.com/arvidOtt)) - [#​4223](https://togithub.com/mochajs/mocha/issues/4223): The context object's `skip()` (`this.skip()`) in a "before all" (`before()`) hook will no longer execute subsequent sibling hooks, in addition to hooks in child suites ([**@​juergba**](https://togithub.com/juergba)) - [#​4178](https://togithub.com/mochajs/mocha/issues/4178): Remove previously soft-deprecated APIs ([**@​wnghdcjfe**](https://togithub.com/wnghdcjfe)): - `Mocha.prototype.ignoreLeaks()` - `Mocha.prototype.useColors()` - `Mocha.prototype.useInlineDiffs()` - `Mocha.prototype.hideDiff()` #### 🎉 Enhancements - [#​4245](https://togithub.com/mochajs/mocha/issues/4245): Add ability to run tests in parallel for Node.js (see [docs](https://mochajs.org/#parallel-tests)) ([**@​boneskull**](https://togithub.com/boneskull)) ❗ See also [#​4244](https://togithub.com/mochajs/mocha/issues/4244); [Root Hook Plugins (docs)](https://mochajs.org/#root-hook-plugins) -- _root hooks must be defined via Root Hook Plugins to work in parallel mode_ - [#​4304](https://togithub.com/mochajs/mocha/issues/4304): `--require` now works with ES modules ([**@​JacobLey**](https://togithub.com/JacobLey)) - [#​4299](https://togithub.com/mochajs/mocha/issues/4299): In some circumstances, Mocha can run ES modules under Node.js v10 -- _use at your own risk!_ ([**@​giltayar**](https://togithub.com/giltayar)) #### 📖 Documentation - [#​4246](https://togithub.com/mochajs/mocha/issues/4246): Add documentation for parallel mode and Root Hook plugins ([**@​boneskull**](https://togithub.com/boneskull)) #### 🐛 Fixes (All bug fixes in Mocha v8.0.0 are also breaking changes, and are listed above) </details> --- ### Renovate configuration 📅 **Schedule**: "after 9am and before 3pm" (UTC). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻️ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/nodejs-dialogflow).
* feat!: Update library to use Node 12 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
This PR was generated using Autosynth. 🌈 Synth log will be available here: https://source.cloud.google.com/results/invocations/91408a5a-0866-4f1e-92b1-4f0e885b0e2e/targets - [ ] To automatically regenerate this PR, check this box.
This PR was generated using Autosynth. 🌈 Synth log will be available here: https://source.cloud.google.com/results/invocations/91408a5a-0866-4f1e-92b1-4f0e885b0e2e/targets - [ ] To automatically regenerate this PR, check this box.
- [ ] Regenerate this pull request now. PiperOrigin-RevId: 468790263 Source-Link: googleapis/googleapis@873ab45 Source-Link: googleapis/googleapis-gen@cb6f37a Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiY2I2ZjM3YWVmZjJhMzQ3MmU0MGE3YmJhY2U4YzY3ZDc1ZTI0YmVlNSJ9
When I view an entity in the web based datastore viewer I see a big long guid-esq string that I can normally use in Python to walk back to the entity without knowing its type, for example:
get me back a specific entity and with Python I can get to this by saying:
Can this be done with the gcloud nodejs library and/or is this entirely a bad method for some reason to begin with? Thanks!
The text was updated successfully, but these errors were encountered: