I'm using MongoDB connector and have a Considerate and Discussion model setup like this:
model-config.json:
{
"Considerate": {"dataSource": "db"},
"Discussion": {"dataSource": "transient"}
}
considerate.json:
{
"name": "Considerate",
"base": "PersistedModel",
"relations": {
"discussion": {"type": "embedsOne", "model": "Discussion"}
}
}
discussion.json:
{
"name": "Discussion",
"base": "Model",
"properties": {
"name": {"type": "string"}
},
"relations": {
"considerate": {"type": "belongsTo", "model": "Considerate"}
}
}
}
How can I query for Considerates based on Discussion's properties? For example, something like this:
Considerate.find({where: {'discussion.name': 'snow white'}})
Inspecting Mongo persisted data, I see that in each Considerate document, there's a _discussion property. Consequently, Considerate.find({where: {'_discussion.name': 'snow white'}}) works. However, this is undocumented and wondering if there is a documented/reliable way to to this.
You can use the filters in the REST APIs wherever you want data from your relations. Eg: [include][relationName]
I think you can also pass data to the fields here.
https://docs.strongloop.com/display/public/LB/Where+filter
This might help you too
https://github.com/strongloop/loopback/issues/517
Related
I am trying to use a "LIKE" search on DynamoDB where I have an array of objects using nodejs.
Looking through the documentation and other related posts I have seen this can be done using the CONTAINS parameter.
My question is - Can I run a scan or query over all of my items in DynamoDB where a value in my object is LIKE "Test 2".
Here is my DynamoDB Table
This is how it looks as JSON:
{
"items": [
{
"description": "Test 1 Description",
"id": "86f550e3-3dee-4fea-84e9-30df174f27ea",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/86f550e3-3dee-4fea-84e9-30df174f27ea.jpg",
"live": 1,
"status": "new",
"title": "Test 1 Title"
},
{
"description": "Test 2 Description",
"id": "e17dbb45-63da-4567-941c-bb7e31476f6a",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/e17dbb45-63da-4567-941c-bb7e31476f6a.jpg",
"live": 1,
"status": "new",
"title": "Test 2 Title"
},
{
"description": "Test 3 Description",
"id": "14ad228f-0939-4ed4-aa7b-66ceef862301",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/14ad228f-0939-4ed4-aa7b-66ceef862301.jpg",
"live": 1,
"status": "new",
"title": "Test 3 Title"
}
],
"userId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
I am trying to perform a scan / query which will look over ALL users (every row) and look at ALL items and return ALL instances where description is LIKE "Test 2".
I have tried variations of scans as per the below:
{
"TableName": "my-table",
"ConsistentRead": false,
"ExpressionAttributeNames": {
"#items": "items",
},
"FilterExpression": "contains (#items, :itemVal)",
"ExpressionAttributeValues": {
":itemVal":
{
"M": {
"description": {
"S": "Test 2 Description"
},
"id": {
"S": "e17dbb45-63da-4567-941c-bb7e31476f6a"
},
"image": {
"S": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/e17dbb45-63da-4567-941c-bb7e31476f6a.jpg"
},
"live": {
"N": "1"
},
"status": {
"S": "new"
},
"title": {
"S": "Test 2 Title"
}
}
}
}
}
The above scan works but as you can see I am passing in the whole object as an ExpressionAttributeValues, what I want to do is just pass in the description for example something like the below (which doesnt work and returns no items found).
{
"TableName": "my-table",
"ConsistentRead": false,
"ExpressionAttributeNames": {
"#items": "items.description",
},
"FilterExpression": "contains (#items, :itemVal)",
"ExpressionAttributeValues": {
":itemVal":
{
"S": "Test 2"
}
}
}
Alternatively, would it be better to create a separate table where all the items are added and they are linked via the userId? I was always under the impression there should be one table per application but in this instance I think if I had all the item data at the top level, scanning it would be a lot safer and faster.
So with nearly 200 views since posting and no responses I have come up with a solution that does not immediately solve the initial problem (I honestly do not think it can be solved) but have come up with an alternative approach.
Firstly I do not want two tables as this seems overkill, and I do not want the aws costs associated with two tables.
This has lead me to restructure the primary keys with prefixes which I can search over using the "BEGINS_WITH" dynamodb selector query.
Users will be added as U_{USER_ID} and items will be added as I_{USER_ID}_{ITEM_ID}, this way I only have one table to manage and pay for and this allows me to run BEGINS_WITH "U_" to get a list of users or "I_" to get a list of items.
I will then flatten the item data as strings so I can run "contains" searches on any of the item data. This also allows me to run a "contains {USER_ID}" search on the primary keys for items so I can get a list of items for a particular user.
Hope this helps anyone who might come up against the same issue.
This is my response.
[
{
"id": 123,
"name": "text1"
},
{
"id": 456,
"name": "text2"
},
{
"id": 789,
"name": "text3"
}
]
I can just provide the name value and want to get back the id attribute. I am using rest assured. I can create a map and then get it accordingly but searching for solutions like jsonPath().get(id where name ="text2"). Just thinking if anything can be done like that.
You can use conditions like .find{it.name=='text2'}.id
I am designing a REST API and in this particular use case, trying to figure out the best way and what this hypermedia should look like.
The scenario is that the caller calls /persons?fields=lastName;filter=beginsWith=b because he wants back a list of people whos last names begin with "b".
Below shows the JSON response that I'm trying to figure out how best to mold/represent including hypermedia to associate with.
You can see a list of persons and you only see the name property because it's a partial representation of each person.
Then I try to add HATEAOS in here but not sure what would be the most useful to add and really what that should reference.
I figured ok, I can provide a href to the group (list) itself that I'm returning here. And if that's the case, where? I don't think it makes sense to put it in a root object like I'm doing. Because the expectation is to return a list of people, not also some root meta object so it doesn't feel good to me on what I have below.
OR
Does anyone think it isn't useful or not really embracing the HATEOS in this particular instance and I should instead provide some other type of href links in here?
JSON - List of person objects (representations) returned
[
"meta": {
"rel": "self",
"href": "http://ourdomain.api/persons?fields=lastName;filter=beginsWith=b"
},
{
"name": {
"last": "best"
}
},
{
"name": {
"last": "bettler"
}
},
{
"name": {
"last": "brown"
}
}
]
well, it is really your choice here, but I think that if you exclude a representation from navigability (i.e. not providing links to it) then it isn't HATEOAS anymore (just my opinion here).
In my opinion you could do something along the lines of the json you provided in the question, just separate clearly what is the result of the call and what is meta-information :
{
"meta": {
"rel": "self",
"href": "http://ourdomain.api/persons?fields=lastName;filter=beginsWith=b"
},
"resource" : [
{
"name": {
"last": "best"
}
},
{
"name": {
"last": "bettler"
}
},
{
"name": {
"last": "brown"
}
}
]
}
which is not so uncommon. Another approach would be to provide links to the list in every resource you return, with a relation like parent or source (maybe source makes more sense as it is a filtered query), e.g.
{[
{ "name" : {
"last" : "best"
},
"meta": {
"rel": "source",
"href": "http://ourdomain.api/persons?fields=lastName;filter=beginsWith=b"
}
},
{ ..and so on.. }
]}
after all, the list is just a container for the results, so it would feel more 'clean' (at least to me) not to have any hypermedia in it.
With Ember Data and Jsonapi. How is a json paginated resource supposed to look like?
I built my response so it looks like:
"meta": {
"page": {
"number": 1,
"size": 5,
"total": 39
}
},
"links": {
"self": "http://localhost:3099/api/v1/articles",
"prev": null,
"next": "http://localhost:3099/api/v1/articles?page[number]=2",
"first": "http://localhost:3099/api/v1/articles?page[number]=1",
"last": "http://localhost:3099/api/v1/articles?page[number]=39"
},
"data": [
...
]
But I am not exactly sure if this is the right format. based on the explanation at http://jsonapi.org/format/#fetching-pagination
Or, are the pagination links (i.e. prev, next, first and last) supposed to be in meta.page ?
You could use ember-cli-pagination and its format to do pagination. I'm pretty sure Ember Data does not follow the JSON API spec strictly.
Based on your sample this could be a format:
{
"meta": {
"total_pages": 3,
"page": 1
},
"articles": [
{"id": 1, "title": "Hello World", "body": "More to Come"},
// ......
]
}
The request URL of this payload could be http://localhost:3099/api/v1/articles?page=1. See the API for more info.
Ember Data doesn't follow the JSON spec strictly so you should concentrate more on setting up the JSON with what ED needs. I would personally move the 'links' info into the meta tag. Otherwise Ember-Data will attempt to put them into a model called 'links', which may not be what you want. If you do intend to store those inside a separate 'links' model, then what you have is fine.
we would like to add lazy loading functionality to our ember project, but it looks like ember will always override fields not returned by the response JSON with NULL. First I get a list of users:
GET https://example.com/users
{
"users": [
{
"id": 1,
"name": 'user1',
"email": 'email#user1.com',
"images": [],
"posts": []
},
{
"id": 2,
"name": 'user2',
"email": 'email#user2.com',
"images": [],
"posts": []
},
{
"id": 3,
"name": 'user3',
"email": 'email#user3.com',
"images": [],
"posts": []
},
]
}
This provides a minimal set of user information, with two empty hasMany relations "images" and "posts".
Now, if somebody want to see the users posts or images he would click a button which triggers the lazy loading:
GET https://example.com/userImages/1
{
"user": {
"id": 1,
"images": [1,2,3,4]
},
"images": [
{
"id": 1,
"name": "image1",
"path" "path/to/img1/"
},
{
"id": 2,
"name": "image2",
"path" "path/to/img2/"
},
{
"id": 3,
"name": "image3",
"path" "path/to/img3/"
},
{
"id": 4,
"name": "image4",
"path" "path/to/img4/"
}
]
}
To reduce traffic to a minimum, only the newly loaded information is included. After the adapter has deserialzed and pushed the new data to the store, all fields from User1 which are not included in the payload (name, email) are set to NULL in the ember store (tested with store.pushPayload('model', payload)).
Is there a possibility to update only incoming data? Or is there a common best practice to handle such a case?
Thanks in advance for your help
EDIT:
One possibility would be to extend the ember-data "_load()" function with the block
for (var key in record._data) {
var property = record._data[key];
if( typeof(data[key]) == 'object' && data[key] == null ) {
data[key] = property;
}
}
But this is the worst possible solution I can imagine.
I think what you want is the store's update method. It's like push (or pushPayload), except that it only updates the data that you give it.
Your property returns a promise and that promise returns whatever came back from the server.
foobar: function() {
return this.store.find('foobar');
}
When the promise resolves, you have two versions of the data, the one already rendered in the client (dataOld) and the one that just returned from the backend (dataNew). To update the client without removing what hasn't change, you have to merge the old and the new. Something along the lines of:
foobar: function() {
var dataOld = this.get('foobar');
return this.store.find('foobar').then(function(dataNew) {
return Ember.$.merge(dataOld, dataNew);
});
}