I have 2 different kind of storage for a CMS that I am building. A relational database and a content repository (PHPCR + Doctrine ODM). I have a User which is stored inside the relational database and I have a Post document which is stored inside PHPCR. How would I get all posts for all active users.
Psuedo code (for demonstration purpose):
$qb = $this->createQueryBuilder('Document\Post', 'post');
$qb->join('post.user', 'user'); // We join on the table inside a relation database
$qb->where('user.active = 1');
$posts = $qb->getQuery()->execute(); // All posts objects of active users
Is this even possible? Or do I need to use 1 type of storage (relational or PHPCR) for all of my data?
Hope somebody can help me out!
You can not join over the different databases. If you do not have thousends and thousands of users, you could just map them into PHPCR. Otherwise you could do two queries. One on the ORM to fetch your user(s) and then one on PHPCR-ODM to fetch all posts that have a username that is one of the users you are looking for.
For links from ORM to PHPCR, you can use the "referenceable" feature of documents and store the UUID in the relational database. You can find a document by UUID:
$dm->find(null, $uuid)
Related
I am working on an app which allows users to upload resources to the internet.
I'm struggling with how to write a resolver for fetching resources posted by a specific user.
I have 3 DynamoDB tables
UserTable -> a collection for user
PostTable -> a collection for resources
PostUserTable -> a collection for storing relations between User and Post
In a traditional RDBS, it would be done by joining 2 tables(UserTable and PostTable) using PostUserTable. Even though DynamoDB, or any kinds of NoSQL database allows us to have a more flexible way to store data, I expect(hope) each user has many resources at the end of the day, so I decided to design tables in the same way as RDMS.
But I'm not sure how you can write a resolver for filtering posts only by a specific user? I have a graphql query named getMyPosts and I want it to return posts uploaded by me.
If you go to the AppSync console and click "Attach" on a field to add a resolver, there is a drop down in the top right of each resolver template code editor that has a number of commented examples of how to craft resolver templates for DynamoDB. This is a good place to start and has multiple examples of filters and more. You can read more about the full DynamoDB filter syntax here: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression.
I am building an iOS app that is using Cloud Firestore (not Firebase realtime database) as a backend/database.
Google is trying to push new projects towards Cloud Firestore, and to be honest, developers with new projects should opt-in for Firestore (better querying, easier to scale, etc..).
My issue is the same that any relational database developer has when switching to a no-SQL database: data modeling
I have a very simple scenario, that I will first explain how I would configure it using MySQL:
I want to show a list of posts in a table view, and when the user clicks on one post to expand and show more details for that post (let say the user who wrote it). Sounds easy.
In a relational database world, I would create 2 tables: one named "posts" and one named "users". Inside the "posts" table I would have a foreign key indicating the user. Problem solved.
Poor Barry, never had the time to write a post :(
Using this approach, I can easily achieve what I described, and also, if a user updates his/her details, you will only have to change it in one place and you are done.
Lets now switch to Firestore. I like to think of RDBMS's table names as Firestore's collections and the content/structure of the table as the documents.
In my mind i have 2 possible solutions:
Solution 1:
Follow the same logic as the RDBMS: inside the posts collection, each document should have a key named "userId" and the value should be the documentId of that user. Then by fetching the posts you will know the user. Querying the database a second time will fetch all user related details.
Solution 2:
Data duplication: Each post should have a map (nested object) with a key named "user" and containing any user values you want. By doing this the user data will be attached to every post it writes.
Coming from the normalization realm of RDBMS this sounds scary, but a lot of no-SQL documents encourage duplication(?).
Is this a valid approach?
What happens when a user needs to update his/her email address? How easily you make sure that the email is updated in all places?
The only benefit I see in the second solution is that you can fetch both post and user data in one call.
Is there any other solution for this simple yet very common scenario?
ps: go easy on me, first time no-sql dev.
Thanks in advance.
Use solution 1. Guidance on nesting vs not nesting will depend on the N-to-M relationship of those entities (for example, is it 1 to many, many to many?).
If you believe you will never access an entity without accessing its 'parent', nesting may be appropriate. In firestore (or document-based noSQL databases), you should make the decision whether to nest that entity directly in the document vs in a subcollection based on the expect size of that nested entity. For example, messages in a chat should be a subcollection, as they may in total exceed the maximum document size.
Mongo, a leading noSQL db, provides some guides here
Firestore also provided docs
Hope this helps
#christostsang I would suggest a combination of option 1 and option 2. I like to duplicate data for the view layer and reference the user_id as you suggested.
For example, you will usually show a post and the created_by or author_name with the post. Rather than having to pay additional money and cycles for the user query, you could store both the user_id and the user_name in the document.
A model you could use would be an object/map in firestore here is an example model for you to consider
posts = {
id: xxx,
title: xxx,
body: xxx,
likes: 4,
user: {refId: xxx123, name: "John Doe"}
}
users = {
id: xxx,
name: xxx,
email: xxx,
}
Now when you retrieve the posts document(s) you also have the user/author name included. This would make it easy on a postList page where you might show posts from many different users/authors without needed to query each user to retrieve their name. Now when a user clicks on a post, and you want to show additional user/author information like their email you can perform the query for that one user on the postView page. FYI - you will need to consider changes that user(s) make to their name and if you will update all posts to reflect the name change.
Coming from a mongodb background, I'd like to set up a document with an embedded collection.
For instance if I have a profile object
Profile
name : string
followers : [
name: string
]
such that it has an embedded collection of followers.
Is there a way that I can create an index on Profile so that I can query for all profiles where Profile.Followers includes myUsername?
In short I can query for profiles I'm following from a dynamoDB table?
In mongo I can easily do this by setting up an index on Profile.followers and doing an $in query. Is there something similar for dynamodb?
This documentation suggests there is nothing like an in clause
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html
Currently DynamoDB does not support indices for non scalar types (i.e. Set, List, or Map data types - see here: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html). If you have a separate users table, you can keep track of all profiles you are following in a Set/List attribute.
I want using drupal for create a website.
it's very important for me to know drupal is support ORM.
and me know that drupal 7.0 and upper using orm but it's not clear for me .
any one can help me completly to know about drupal orm?
thank you.
Drupal 7 doesn't use a real ORM like Doctrine, it uses a proprietary database API as referenced on Drupal.org. So you don't write full SQL statements directly but write it using their API to assemble a query.
So yes it acts as a type of ORM but it's not one that's used outside of the Drupal project.
Examples make things easier: from https://drupal.org/node/310075
Regular SQL:
<?php
$result = db_query("SELECT uid, name, status, created, access FROM {users} u WHERE uid <> 0 LIMIT 50 OFFSET 0");
?>
Drupal DB API:
<?php
// Create an object of type SelectQuery
$query = db_select('users', 'u');
// Add extra detail to this query object: a condition, fields and a range
$query->condition('u.uid', 0, '<>');
$query->fields('u', array('uid', 'name', 'status', 'created', 'access'));
$query->range(0, 50);
?>
In addition to the database abstraction layer mentionned in Steve's answer, Drupal 7+ has provide an Entity API (completed by the Entity API module). It evolved from the the node system, completed by the CCK module, from Drupal 6. It does provide abstraction to store, query and retrieve data using objects, but the Entity API is not an ORM, and it does no attempt to be one.
Am I missing a point with Doctrine? It's been very useful for some scenarios, but for the basic scenario of retrieving an entity using an Id (say using find() or findOneBy()) why do you see a query being fired off for every relationship to populate the main entity's properties?
Surely with the mapping/annotations I've created, Doctrine should be capable of a few joins and one query, without having to write a DQL query for the retrieval of each entity.
Or, as I'm predicting, have I missed the point somewhere!
Just add the aliases of related entities to select part of your query.
Let’s say, you have Book related one-to-many to Cover, and you want so select some books with their covers.
With query builder, use:
->createQueryBuilder()
->select("book, cover")
->from("Book", "book")
->leftJoin("book.covers", "cover")
With query, use:
SELECT book, cover FROM Book book LEFT JOIN book.covers cover
As the result, you will receive collections of Book with prepopulated $covers collection.
Because the relationships are hydrated only when needed - by default Doctrine uses a lazy-loading strategy.
If you already know that you will access the related entities, you should build a DQL query that retrieves the record AND the related entities.