I read in this post that easy tables can have relational database features like join etc for combining tables while querying data. Unfortunately I haven't been able to find much about how to go about doing this.
In my case i have an easy table user and another called subject choice having userid attribute in common and i need to retrieve information in a mobile service app based on info in both of these tables.
How do I go about this?
You can manipulate the easy tables query from the easy api script editor.
You will see a .json and .js file for each "easy table" you created. There will be a commented table.read function with the same signature as my example below. Uncommenting this function and modifying the content allows any kind of custom manipulation server side.
So to do a "Join" you COULD fetch the records from both tables yourself, and then return a "combined" json object.
Here is an example of fetching the data from the storage and deciding when to return:
table.read(function (context) {
var response = context.execute();
response.then(function (records)
{
console.log("Records Fetched: " , records);
// HERE YOU CAN MESS WITH THE DATA
context.res.status(200).send(records);
context.done();
}, function (error)
{
console.log(error);
context.res.status(500).send(error);
context.done();
});
});
According to your description, I followed this tutorial for getting started with the Easy Tables of Azure Mobile App. In my opinion, Easy Tables could provide you with a simple way to add back-end data storage for your mobile app.
We could wrap the operations to the specific table as follows:
public class UserDataService
{
MobileServiceClient mobileService;
IMobileServiceTable<User> userTable;
public void Initialize()
{
mobileService= new MobileServiceClient("http://<your-mobileapp-name>.azurewebsites.net/");
userTable = mobileService.GetTable<User>();
}
public async Task<User> GetUserAsync(string uid)
{
return await this.userTable.LoolupAsync(uid);
}
public async Task AddUserAsync(User user)
{
await this.userTable.InsertAsync(user);
}
}
easy tables can have relational database features like join etc for combining tables while querying data.
As far as I know, you could add a foreign key in a Easy Table for creating your relationships. But you couldn't retrieve data from multiple tables in a single query. For your scenario, you could invoke the methods UserDataService.GetUserAsync and SubjectChoiceDataService.GetByUserIdAsync to aggregate the data as you expected.
Related
I am creating a Laravel Application with Eloquent connected to MySQL DBMS where I have three models:
Product
ProductGallery
File
I have also the following relations
One Product has one ProductGallery
One ProductGallery has many File
My question is:
Is it okay if I store images in ProductGallery as an array of file_ids
instead of creating a join table or having gallery_id in File model?
public function setImagesAttribute($images)
{
$this->attributes['images'] = serialize($images);
}
public function getImagesAttribute()
{
if (empty($this->attributes['images']) || is_null($this->attributes['images'])) return [];
return unserialize($this->attributes['images']);
}
I am asking this question to know if there is any side effects for this method
and in the future there might be other models related to File model (Category may have featured image file and so on).
In my opinion Better Option is creating a pivot table.. Because further when you have to join , you pull the array and you have to execute a query under a loop that is bad..
I am using PubSubToBigQuery.java code without any changes. Would someone please show me how to remove duplicate records during this process?
I know the trick is to create Window and use GroupBy but really not know how to write it.
Thanks
Assuming you just want to filter duplicate on successful parsed events. You will need to add some code after this line:
transformOut
.get(TRANSFORM_OUT)
.apply("keyed", WithKeys.of(/* choose your key from table row to identify duplicates */))
.apply(GroupByKey.create())
.apply("dedup", ParDo.of(new DoFn<KV<String, Iterable<TableRow>>, TableRow>() {
public void ProcessElement(ProcessContext context) {
// only output one element from list to dedup.
context.output(context.element().getValue().iterator().next());
}
}
))
.apply(Window.configure().triggering(/* choose your trigger */)
.apply(
"WriteSuccessfulRecords",
BigQueryIO.writeTableRows()
.withoutValidation()
.withCreateDisposition(CreateDisposition.CREATE_NEVER)
.withWriteDisposition(WriteDisposition.WRITE_APPEND)
.to(options.getOutputTableSpec()));
BeamSQL actual tries to support your use case (check PubsubToBigqueryIT.java). BeamSQL allows you create table on pubsub topic and bigquery table. Read from pubsub, convert pubsub messages and write to BQ table are handled by BeamSQL already. SQL can be applied to data that read from pubsub. However, BeamSQL might miss some features (for example, ANY_VALUE aggregation function if you want use group by to dedup in SQL) to finish your task.
I have a database with some complex relationships mapped and populated with a large amount of data. My requirement is that I need to use this database with Swift-Vapor server.
So that I created a model object (with Fluent framework constructs) similar to the database schema, in order to handle data flows between the vapor server and db.
When it comes the time to link database table(users table) with the model(User model), I found this method, which should implement inside the model class.
static func prepare(_ database: Database) throws {
try database.create("users") { users in
users.id()
users.string("name")
}
}
Since I don't need to define a schema for already existing db, this prepare method just left unimplemented.
The result is that I just can't interact with db, for any operations like userObj.save()
The same thing I achieved with Swift-Perfect Server with the help of the following method implementation inside the model object. This was done with the help MySQLStORM in Perfect.
// Map the model to the database table "user"
override open func table() -> String {
return "user"
}
What I'm looking for is -> Is there any option like this available in Vapor so that I can map model object to a database table?
Got a solution while discussing this issue in Slack community, tried out and working fine.
Solution:
In the model class (say User), the prepare method can be left unimplemented, like
static func prepare(_ database: Database) throws {
}
But should add a static variable entity which will have the table name mapped, like
final class User: Model {
static let entity = "users"
...
}
And finally, we should add the model to the droplets preparations array, like
// Let the User be your model object
drop.preparations.append(User.self)
So that we can use any existing database with complex relations or pre-populated data tables to map with the model object, without constructing tables from model object.
I have an array of objects related to users and want to get all objects related to one user. I can't save the userid as a parent node but as a child so that I want to use the equalTo method.
ref.orderByChild("userid").equalTo(uid).on("child_added", function(snapshot) {
console.log(snapshot.val());
});
Does this first query all objects (slow) and then select only the required ones or does firebase optimize the query itself on the server? I come from SQL and I am a bit unsure how to handle where queries in firebase.
Edit: there are also security issues. A user could receive all objects by hacking the js code? I hope the security rules should solve this?
Example JSON:
{
Objectkey1: { userid: 'uid', ... },
Objectkey2: { userid: 'uid', ... },
...
}
Does this first query all objects (slow) and then select only the required ones or does firebase optimize the query itself on the server?
Yup, that's pretty much what happens. So this operation will always get slower as you add more items to the location identified by ref.
If that type of performance is a concern (i.e. if you care about scalability), consider adding an inverted/secondary index to the thing that user identified by uid.
I have lightswitch entities created in the HTML5 client. There is a field that the user should not be setting that needs to be set based on their login. In this case, the client the user is associated with.
The standard examples (in Michael Washington's book Creating HTML 5 Websites ... Using Lightswitch and all over the web) involve assigning the user name as the relevant field, setting up a little handler on the server to return the relevant field using an AJAX call.
This is was all well and good while prototyping, but now that we are doing this for real, there is a relationship to another entity involved, the Client Entity, so you can't just assign the Client Id. So instead of simply assigning a Client ID, now we have associate a whole Client Object to the entity.
Here the suggestion is to do what ends up looking like this:
myapp.activeDataWorkspace.ApplicationData.Clients_SingleOrDefault(1).execute().then(function (ClientQuery) {
entity.setClient(ClientQuery.results[0]);
});
My problem is with this part:
Clients_SingleOrDefault(1)
I need to get that number dynamically, not just a hard coded 1, as that OP suggested. So I can do it in two server calls, one to get the ID, and then the next one to substitute that result into the next call, but that seems ... inefficient.
msls.promiseOperation(CallGetClientId).then(function PromiseSuccess(PromiseResult) {
myapp.activeDataWorkspace.ApplicationData.Clients_SingleOrDefault(Number(PromiseResult)).execute().then(function (ClientQuery) {
entity.setClient(ClientQuery.results[0]);
});
});
function CallGetClientId(operation) {
$.ajax({
type: 'post',
data: {},
url: '../UserCode/GetClientId.ashx',
success: operation.code(function AjaxSuccess(AjaxResult) {
operation.complete(AjaxResult);
})
});
}
It would seem that there should be a better way to do it. Is there?
The simplest method of achieving this with one server call is to implement a scalar query.
For example, if you create a scalar query called ClientForCurrentUser against your Clients table you'd be able to make a single client side call as follows:
myapp.activeDataWorkspace.ApplicationData.ClientForCurrentUser().execute().then(function (query) {
if (query && query.results && query.results.length !== 0) {
entity.setClient(query.results[0]);
}
});
As regards configuring the scalar query, the following post covers an example (note the setting of the 'Number of Results Returned' property):
Applying where clause to child collection in LightSwitch query
Then, assuming you have a field against your Client record that relates it to the current username (e.g. Client.RelatedUser) you'd implement the following type of PreprocessQuery method against the scalar query:
partial void ClientForCurrentUserPersonForCurrentUser_PreprocessQuery(ref IQueryable<Client> query)
{
var username = this.Application.User.Name;
query = query.Where(c => c.RelatedUser.Equals(username, StringComparison.OrdinalIgnoreCase)).Take(1);
}