Loopback 4 - Eager Load Detail Table - loopbackjs

I'm new to Loopback 4 and am having an issue mapping our current database structure to the ORM. We currently use detail tables a lot to store secondary object data, such as addresses. For example we might have two tables related as so:
"Offices" table
id: string;
officeName: string; "Addresses" table
addressId: string; ============> id: string;
line1: string;
line2: string;
city: string;
state: string;
zip: number;
Then we use a DTO to map the data as follows:
"Office" DTO
id: string;
officeName: string;
addressLine1: string;
addressLine2: string;
addressCity: string;
addressState: string;
addressZip: number;
However i'm having trouble figuring out how to eager load the address detail table so when I create the DTO using the model it will map correctly. I can see how to do this manually, but I'm looking for a solution that eager loads the child "address" record with the parent "office" record.
For reference I've set up my models and repositories as documented here:
https://loopback.io/doc/en/lb4/BelongsTo-relation.html
The office belongs to the address, since the address primary key is stored in the office record.

Update: Turns out this is not possible/hasn't been implemented yet. Our next solution will unfortunately not include Loopback due to this.
Source: https://github.com/strongloop/loopback-next/issues/1352

Related

Azue Map Search: unique ID and normalized name

I use azure maps for cities autocomplete on my site.
I use this API method: https://learn.microsoft.com/en-us/rest/api/maps/search/getsearchaddress
Request: https://atlas.microsoft.com/search/address/json?params and parameters are:
query=mosco - I'm looking for Moscow
typehand=true
api-version=1.0
subscription-key=...my key...
Result is
{
...
results: [
{
type: "Geography",
id: "RU/GEO/p0/116970,
...
address: {
municipality: "Moscow",
countryCode: "RU",
freeformAddress: "Moscow"
}
},
...
],
}
Ok, it's Moscow.
But I have a few questions.
What is id? Doc say it is "property id". It is persistent? Moscow will always be "116970"?
How can I get normalize name of a city?
I can write "Москва" (Moscow in Russian) and it works and id is same, but names in the object address are different (Москва, Moscow).
If I write "mos" then id is same but address is "Moskva" (instead Moscow).
Can I get name of a geo object by id?
This is a unique id but is not guaranteed to be persistent. The main purpose of this id is for debugging purposes.
We are aware of the "en" issue and are updating the docs.
I sure this is a unique ID, but want proof from documentation :)
Problem solved by parameter language=en-GB now result always is "Moscow". I was misled by the manual when specified only en (it leads to error). https://learn.microsoft.com/en-us/azure/azure-maps/supported-languages

DynamoDB Search with HashKey

I have table with the following structure
HashKey: Place Name
Attribute: Place Data Class
now i would like to search with Place Name,
Ex: I have below data
Newyork {lat: x.xxxxx, lng: x.xxxxxx}
Newzealand {lat: x.xxxxx, lng: x.xxxxxx}
IndialaPolis {lat: x.xxxxx, lng: x.xxxxxx}
when i searching with keyword new, it should return Newyork and Newzealand, I searched google for this, i found that we can get all records by the HashKey
When doing a Query, you can only have exact matches on the HashKey.
However, there is also the Scan operation, that you can use along with a FilterExpression. Just note that Query and Scan perform and consume capacity differently. See the differences here.
Here are example parameters you could use on a Scan with begins_with:
{
table_name: tableName,
filter_expression: "begins_with(#country, :search)",
expression_attribute_names: {
"#country" => "country"
},
expression_attribute_values: {
":search" => "new"
}
}
This article is a good place to start.
Thank you #mark-b and #bruno-buccolo, as you said it is not possible to Search hashkey field
So i created Elastic Search Indexes for that table manually and updating each time the original record updates

Ember Data and Handsontable recursion

When a Handsontable is instantiated, it calls a recursive method to build a data schema: https://github.com/handsontable/handsontable/blob/be8654f78ca84efc982047ca6b399e6c6d99f893/src/dataMap.js#L28, which in turns calls objectEach: https://github.com/handsontable/handsontable/blob/master/src/helpers/object.js#L235-L245
However, with an Ember Data record, it tries to iterate over properties like store, which means it gets caught in an endless loop.
Is there any way to bypass the recursiveDuckSchema method?
Unless Handsontable has some interface to allow pre-parsing data before it reaches the core of the plugin, I would say you may have better luck by transforming your ember-data models into something handsometable understands.
let queryParams = //Your query params
let data = this.get('getTheContent'); //Your models
let handsomeData = data.map(function(item, index, enumerable)){
return { id: item.get('id'), name: item.get('name'), other: item.get('other') }
};
// Result is [{id: 1, name: 'John', other: 'Other'}, {...}]

Should I denormalize or run multiple queries in DocumentDb?

I'm learning about data modeling in DocumentDb. Here's where I need some advice
Please see what my documents look like down below.
I can take two approaches here both with pros and cons.
Scenario 1:
If I keep the data denormalized (see my documents below) by keeping project team member information i.e. first, last name, email, etc. in the same document as the project, I can get the information I need in one query BUT when Jane Doe gets married and her last name changes, I'd have to update a lot of documents in the Projects collection. I'd also have to be extremely careful in making sure that all collections with documents that contain employee information get updated as well. If, for example, I update Jane Doe's name in Projects collection but forget to update the TimeSheets collection, I'd be in trouble!
Scenario 2:
If I keep data somewhat normalized and keep only EmployeeId in the project documents, I can then run three queries whenever I want to get a projects list:
Query 1 returns projects list
Query 2 would give me EmployeeId's of all project team members that appear in the first query
Query 3 for employee information i.e. first, last name, email, etc. I'd use the result of Query 2 to run this one
I can then combine all the data in my application.
The problem here is that DocumentDb seems to have a lot of limitations now. I may be reading hundreds of projects with hundreds of employees in project teams. Looks like there's no efficient way to get all employee information whose Id's appear in my second query. Again, please keep in mind that I may need to pull hundreds of employee information here. If the following SQL query is what I'd use for employee data, I may have to run the same query a few times to get all the information I need because I don't think I can have hundreds of OR statements:
SELECT e.Id, e.firstName, e.lastName, e.emailAddress
FROM Employees e
WHERE e.Id = 1111 OR e.Id = 2222
I understand that DocumentDb is still in preview and some of these limitations will be fixed. With that said, how should I approach this problem? How can I efficiently both store/manage and retrieve all project data I need -- including project team information? Is Scenario 1 a better solution or Scenario 2 or is there a better third option?
Here's what my documents look like. First, the project document:
{
id: 789,
projectName: "My first project",
startDate: "9/6/2014",
projectTeam: [
{ id: 1111, firstName: "John", lastName: "Smith", position: "Sr. Engineer" },
{ id: 2222, firstName: "Jane", lastName: "Doe", position: "Project Manager" }
]
}
And here are two employee documents which reside in the Employees collection:
{
id: 1111,
firstName: "John",
lastName: "Smith",
dateOfBirth: "1/1/1967',
emailAddresses: [
{ email: "jsmith#domain1.com", isPrimary: "true" },
{ email: "john.smith#domain2.com", isPrimary: "false" }
]
},
{
id: 2222,
firstName: "Jane",
lastName: "Doe",
dateOfBirth: "3/8/1975',
emailAddresses: [
{ email: "jane#domain1.com", isPrimary: "true" }
]
}
I believe you're on the right track in considering the trade-offs between normalizing or de-normalizing your project and employee data. As you've mentioned:
Scenario 1) If you de-normalize your data model (couple projects and employee data together) - you may find yourself having to update many projects when you update an employee.
Scenario 2) If you normalize your data model (decouple projects and employee data) - you would have to query for projects to retrieve employeeIds and then query for the employees if you wanted to get the list of employees belonging to a project.
I would pick the appropriate trade-off given your application's use case. In general, I prefer de-normalizing when you have a read-heavy application and normalizing when you have a write-heavy application.
Note that you can avoid having to make multiple roundtrips between your application and the database by leveraging DocumentDB's store procedures (queries would be performed on DocumentDB-server-side).
Here's an example store procedure for retrieving employees belonging to a specific projectId:
function(projectId) {
/* the context method can be accessed inside stored procedures and triggers*/
var context = getContext();
/* access all database operations - CRUD, query against documents in the current collection */
var collection = context.getCollection();
/* access HTTP response body and headers from the procedure */
var response = context.getResponse();
/* Callback for processing query on projectId */
var projectHandler = function(documents) {
var i;
for (i = 0; i < documents[0].projectTeam.length; i++) {
// Query for the Employees
queryOnId(documents[0].projectTeam[i].id, employeeHandler);
}
};
/* Callback for processing query on employeeId */
var employeeHandler = function(documents) {
response.setBody(response.getBody() + JSON.stringify(documents[0]));
};
/* Query on a single id and call back */
var queryOnId = function(id, callbackHandler) {
collection.queryDocuments(collection.getSelfLink(),
'SELECT * FROM c WHERE c.id = \"' + id + '\"', {},
function(err, documents) {
if (err) {
throw new Error('Error' + err.message);
}
if (documents.length < 1) {
throw 'Unable to find id';
}
callbackHandler(documents);
}
);
};
// Query on the projectId
queryOnId(projectId, projectHandler);
}
Even though DocumentDB supports limited OR statements during the preview - you can still get relatively good performance by splitting the employeeId-lookups into a bunch of asynchronous server-side queries.

Single Table Inheritance and Yaml configuration

I want to use in my project Single Table Inheritance for symfony2/doctrine, but I can't find any working examples with yaml configuration for it. In official documentation there is only annotation configuration presented. I found xml examples, but I want to use yaml configuration. Can somebody help and share with some working code?
Okay built-in converter saves life.
In order to save time this an example of inheritance converted into yaml :
#file: Resources/config/doctrine/Person.orm.yml
Person:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: discr
type: string
length: 255
discriminatorMap:
person: Person
employee: Employee
lifecycleCallbacks: { }
#file: Resources/config/doctrine/Employee.orm.yml
Employee:
type: entity
table: null
lifecycleCallbacks: { }
Here is an example of YAML markup:
Entities config files should be put into src/Acme/StoreBundle/Resources/config/doctrine/<EntityName>.orm.yml according to reference.
Also built-in converter can be used: how to model inheritance in doctrine2 with yaml?