while working on Firestore Security rules, I found out that there is no way to specify read/write-access on a Field-Level.
Everything that can be done is to specify access on a Document/Collection level.
But doesn't this enforce really weird database structures?
Consider this example:
[
{
"id": 15,
"name": "room1",
"color": "red",
"owner": "Tim"
},
{
"id": 642,
"name": "room2",
"color": "green",
"owner": "Charles"
},
{
"id": 989,
"name": "room3",
"color": "blue",
"owner": "Jane"
}
]
In this example I want to make it possible for e.g. Jane to read the Fields id name and owner of every entry in the collection, but I don't want her to see the field color of the rooms of the other persons.
This would be of course be possible with a data structure like this:
[
{
"id": 15,
"name": "room1",
"owner": "Tim",
"private_values": {
"color": "red"
}
},
{
"id": 642,
"name": "room2",
"private_values": {
"color": "green"
},
"owner": "Charles"
},
{
"id": 989,
"name": "room3",
"private_values": {
"color": "blue"
},
"owner": "Jane"
}
]
Everything I did was just move the "private"-values (in this case only the color) into another extra collection.
This way I can just set a rule for the root-object, and another extra rule on the object private_values.
Even though this is entirely possible to do, I wouldn't consider it especially clean when extrapolated to a bigger example where there would be for example more groups of users, who all need to be able to see different fields.
Is there a cleaner and better way to do this than the one I just explained, or is there anything else I missed?
Regards
You didn't miss anything. This is exactly what you're supposed to do. Documents in Firestore are the most granular unit for operations.
Note that you can also not read a partial document (you must read all the fields if you want to read any of the fields). If you write a Cloud Function that triggers when a document changes, you always receive the contents of the entire document, and you can't write a trigger for when an individual field changes.
Related
I'm using different kind of queries to retrive wikidata info of an entity like, for Berlin:
https://www.wikidata.org/wiki/Special:EntityData/Q64.json
https://www.wikidata.org/w/api.php?action=wbgetentities&ids=Q64&format=json
but all of these did not include the full information.
As an example, i'm not able to find the official language or population data.
How can I get all data?
Both of the shown URLs / APIs do should you the full data for the entity that you are looking at, Q64 being Berlin.
In Wikidata the official language is represented by the Property P37 and the population by Property P1082.
You will find references to these properties in the JSON output.
For example for the language:
{
"mainsnak": {
"snaktype": "value",
"property": "P37",
"hash": "b8dce904caadeef339763625b903974aa4c83c6a",
"datavalue": {
"value": {
"entity-type": "item",
"numeric-id": 188,
"id": "Q188"
},
"type": "wikibase-entityid"
},
"datatype": "wikibase-item"
},
"type": "statement",
"id": "Q64$9AEBFCE4-EC53-4A97-B20B-4579FBD32CE7",
"rank": "normal"
}
This refers to Q188 which is German.
I've stubled upon an issue for updating order line items' metadata via WooCommerce REST API using node.js.
I've been following these steps for updating orders (and was succesful with some fields):
https://woocommerce.github.io/woocommerce-rest-api-docs/#update-an-order
Now, what I would like to achieve is changing the number of shipped line items of an order. Something I would normally use the partial orders WC plugin in the wordpress UI.
Below, you can find a screenshot of a line item I get from WC using the orders API call. The last element of the meta_data array has key 'shipped' and it contains an array with one object, stating that one (out of two ordered items) had been shipped:
"line_items": [{
"id": 1937,
"name": "Maya",
"product_id": 1271,
"variation_id": 1272,
"quantity": 2,
"tax_class": "",
"subtotal": "140.00",
"subtotal_tax": "0.00",
"total": "140.00",
"total_tax": "0.00",
"taxes": [],
"meta_data": [{
"id": 21637,
"key": "pa_product-color",
"value": "beige"
}, {
"id": 21638,
"key": "pa_shoe-size",
"value": "42"
}, {
"id": 21639,
"key": "pa_shoe-width",
"value": "wide"
}, {
"id": 21640,
"key": "shipped",
"value": [{
"qty": 1,
"date": "Nov 21, 2017"
}
]
}
],
"sku": "2522BE42W",
"price": 70
},
As you can see, the value of the key 'shipped' is an object. When I ty to send it (back) to WC, I get an error saying:
"data":{"status":400,"params":{"line_items":"line_items[0][meta_data][3][value] is not of type string."}}}
When I try to send the value as a string, i.e.
lineItems[0].meta_data = [{key:"shipped", value: "[{qty:'2'}]" }]
I get no errors, but WC treats this as string, not as an object and doesn't update the shipment qty in the DB the way I intended (it only pulls the shipped quantity down to 0 instead):
{
"id": 21640,
"key": "shipped",
"value": "[{qty:'2'}]"
}
Any insights or ideas - how could I modify the shipped quantity of line items via the WC API?
So, apparently there was a bug in WP 4.9 version, which was fixed recently in the following commit:
https://github.com/woocommerce/woocommerce/pull/17849
It concerns REST API schema and after merging the fix to WooCommerce, the problems disappear and now I am able to send the data as an object.
More on the topic can be found here:
https://github.com/woocommerce/wc-api-dev/pull/74
I am working with Microsoft Cognitive Service's Language Understanding Service API, LUIS.ai.
Whenever text is parsed by LUIS, whitespace tokens are always inserted around punctuation.
This behavior is intentional, according to the documentation.
"English, French, Italian, Spanish: token breaks are inserted at any
whitespace, and around any punctuation."
For my project, I need to preserve the original query string, without these tokens, as some entities trained for my model will include punctuation, and it's annoying and a bit hacky to strip the extra whitespace from the parsed entities.
Example of this behavior:
Is there a way to disable this? It would save quite a bit of effort.
Thanks!!
Unfortunately there's no way to disable that for now, but the good news is that the predictions returned will deal with the original string, not the tokenized one you see in the example labeling process.
Here in the documentation of how to understand the JSON response you can see the example output preservers the original "query" string, and the extracted entities have the zero based character indices ("startIndex", "endIndex") in the original string; this will allow you to deal with the indices instead of parsed entity phrases.
{
"query": "Book me a flight to Boston on May 4",
"intents": [
{
"intent": "BookFlight",
"score": 0.919818342
},
{
"intent": "None",
"score": 0.136909246
},
{
"intent": "GetWeather",
"score": 0.007304534
}
],
"entities": [
{
"entity": "boston",
"type": "Location::ToLocation",
"startIndex": 20,
"endIndex": 25,
"score": 0.621795356
},
{
"entity": "may 4",
"type": "builtin.datetime.date",
"startIndex": 30,
"endIndex": 34,
"resolution": {
"date": "XXXX-05-04"
}
}
]
}
I'm using JMSSerializer and FOSRestBundle. I have a fairly typical object graph, including some recursion.
What I would like to accomplish is that included objects beyond a certain depth or in general are listed only with their ID, but when serialized directly, with all data.
So, for example:
Users => Groups => Users
when requesting /user/1 the result should be something like
{ "id": 1, "name": "John Doe", "groups": [ { "id": 10 }, { "id": 11 } ] }
While when I request /group/10 it would be:
{ "id": 10, "name": "Groupies", "users": [ { "id": 1 }, { "id": 2 }, { "id": 4 } ] }
With #MaxDeph I can hide the included arrays completely, so I get
{ "id": 1, "name": "John Doe", "groups": [] }
But I would like to include just the IDs so that the REST client can fetch them if it needs them, or consult his cache, or do whatever.
I know I can manually cobble this together using groups, but for consistency reasons I was wondering if I can somehow enable this behaviour in my entire application, maybe even with a reference to maxdepth so I can control where to include IDs and where to include full objects?
For the sake of those finding this:
I found no other solution, but doing this with groups works just fine and gives me the result I was looking for.
I'm trying to use Freebase to find out what team a professional athlete belongs to.
So I'm trying to do something like this
[{
"id": null,
"name": "Kobe Bryant",
"type": "/sports/pro_athlete",
"sports_played": []
}]
query editor
and then extract the property "sport_played" to find out what sport the player belongs to. My plan is to then do a more specific query for "basketball_player" or so until I finde the team name. (Is a simpler way to do this?)
However, I already fail at the first step, because in the results, while the properties sport_played and sport_played_professionally contain a single entry, that entry is null:
{
"code": "/api/status/ok",
"result": [{
"id": "/en/kobe_bryant",
"name": "Kobe Bryant",
"sports_played": [
null
],
"type": "/sports/pro_athlete"
}],
"status": "200 OK",
"transaction_id": "cache;cache03.p01.sjc1:8101;2012-06-13T13:30:20Z;0053"
}
I'm confused: I know from browsing the database that there should be a sport value for this player. And the result clearly shows that there is a single value in the "sports_played" list in the result.
But why is it null? Shouldn't is rather be a reference to a Basketball object?
Your query is asking for a list of sports_played but since you only used square braces it will only return a list of the names of all the matching topics.
If you add curly braces to the query you'll see that sports_played actually returns one topic with name = null (which is what your previous query was showing)
[{
"id": null,
"name": "Kobe Bryant",
"type": "/sports/pro_athlete",
"sports_played": [{}]
}]
This is because the expected value of sports_played is a CVT called Sports played which links athletes to sports for specific periods of time. This is so that we can keep track of athletes that have played multiple sports and know which one is the most current.
If you want to see the values inside the CVT object, you'll need to drill down further like this:
[{
"id": null,
"name": "Kobe Bryant",
"type": "/sports/pro_athlete",
"sports_played": [{
"type": "/sports/pro_sports_played",
"sport": {
"id": null,
"name": null
},
"career_start": null,
"career_end": null
}]
}]
Try it in the Query Editor
The sports_played property isn't really what you want here since it's not necessarily correlated with the properties which contain the team information.
Instead you want to use something along the lines of:
{
"id": null,
"name": "Kobe Bryant",
"/basketball/basketball_player/team" : [{"team":null}],
}]
}
if you wanted to get all the teams for all the Kobe Bryants you could use something like:
[{
"id": null,
"name": "Kobe Bryant",
"/soccer/football_player/current_team" : [{"team":null,"optional":true}],
"/basketball/basketball_player/team" : [{"team":null,"optional":true}],
"/american_football/football_player/current_team" :[{"team":null,"optional":true}]
}]
}]
Unfortunately you'll need to go through the schema by hand and pull out the properties of interest by hand since they're not reliably regular enough to query automatically, but there really aren't that many sports to consider, so it shouldn't take very long to assemble your list.