PHP get MongoDBRef with query - php

I was wondering if there is a way to perform a find() and have Mongo automatically return the associated references without having to run getDBRef() once the parent record has been returned.
I don't see it anywhere in the PHP documentation. I can easily support using getDBRef but it doesn't seem as efficient as it could be.
Also...I'm surprised there's no way to select the specific data to return in the linked reference. I may as well just perform another manual find statement so I can control what the return is...but there has to be a more performance oriented way to do this.
Perhaps I should change my methodology and instead of using the PHP library classes for find, generate my own JavaScript command and run it using the MongoCode class? Would that work and if so...I'm wondering what it would look like. scratches head then heads to The Google
Thanks!

MongoDB does not support joins. Database References (DBRefs) just refers to the practice of a field storing an _id referencing another document. There is currently no specific server-side support for this, and hydrating the reference to a document does require another query. Some MongoDB drivers have convenience methods so you don't have to manually do the find. It is equally valid/performant if you want to do your own find() given a DBRef to lookup (or use other criteria to find related documents).
Depending on your use case and data modelling, a more efficient alternative to the DBRef linking could be embedding related data as a subdocument. See the MongoDB wiki info on Schema Design for more examples.
As far as performance goes, it would be better to use PHP queries than MongoCode (JavaScript which needs to be eval'ed on the server). MongoCode is really intended for more limited use such as within Map/Reduce functions. Refer to Server-Side Code Execution for some of the potential limitations with that approach.

Refer: http://docs.mongodb.org/manual/reference/database-references/
Manual references where you save the _id field of one document in another document as a reference. Then your application can run a second query to return the related data. These references are simple and sufficient for most use cases.
DBRefs are references from one document to another using the value of the first document’s _id field, collection name, and, optionally, its database name. By including these names, DBRefs allow documents located in multiple collections to be more easily linked with documents from a single collection.
To resolve DBRefs, your application must perform additional queries to return the referenced documents. Many drivers have helper methods that form the query for the DBRef automatically. The drivers do not automatically resolve DBRefs into documents.
So either way, no matter which type of referencing you are using, you need to do the dereferencing yourself.
Hope it helps!

Related

Doctrine Query builder - how to select based on field inside JSON column

I have a table with a JSON column, it's type longtext (DC2Type:json). This table has an Entity in Doctrine ORM in my Symfony project. I would like to query based on fields inside the JSON column, using the Doctrine query builder I have in a variable $qb
How do I do this? Everything I found online says to install a 3rd-party package to enable this. Is there no way to just do it with Doctrine's query builder without installing another package?
One (maybe dumb) workaround I tried was to treat the column as a string, and do...
$qb->andWhere("my_data LIKE \"%id:\\\"1,%\"");
For example, if I wanted to query the JSON column my_data to find the blobs that contain id":1, in the string. This fails with a very strange syntax error, and isn't the right way to query a JSON field anyway. HOWEVER, doing the LIKE query directly in SQL client works the way I want, so I also don't know why this is failing in Doctrine.
EDIT: This is MySQL / MariaDB.
Doctrine Query Language is pretty limited. It covers only the most basic/common SQL functions, which is enough for like 99% use cases, but not all.
If you have a MariaDB version that natively supports JSON (so 10.2 or later) you can use native functions to work with the JSON data. (If you don't then your workaround is the only option regardless, with perhaps some additional filtering in the application).
To be able to use these functions in DQL you either need to define them yourself or indeed use a third party library like scienta/doctrine-json-functions (note that it has documentation for how to use it with Symfony, and it's really simple).
If you need just a single extra function and for some reason don't want the whole bundle, you could just copy that single class and use it as your own.
Alternatively you can forgo DQL and write SQL directly, but that way you can't hydrate into objects directly and use other Doctrine magic with the data. But it can be enough for simple use cases.

Modifying the SQL Eloquent uses per connection

I'm using the latest version of Laravel to connect to multiple data sources. One of those sources is an old Oracle database that contains a lot of white space thanks to some ancient software requiring string length. Despite this constraint, the fields have since been edited by new software with different requirements, and the columns are all varying length (and thus unknown).
On account of this, I need to edit the SQL that accesses it in order to wrap some pieces of the queries in trim()s. For instance,
$customer = Customer::whereRaw("RTRIM(\"ID\") = TO_CHAR($id)")->get();
I'd like to be able to merely call the find method:
$customer = Customer::find($id)
This is just one example. Pretty much all of the default functions are broken because the queries need some kind of trim prepended to them. I understand how I can affect the dynamic portion of the query, but I need to edit the column ahead of that. Sorry if this is a dumb question and I've just missed something in the documentation.
The easiest way to do this is to create a class that extends Eloquent, with the function for the query. Then modify all of your models to extend the new class instead of Eloquent. This way the models will have all the functionality of Eloquent as well as the functions you create.

Is there a way to get a list of all google datastore "KIND" using queries

I would like to get a list of KINDS from my google app engine datastore using queries (GQL maybe?). For example the way one would simply show tables of a database.
I have looked at a similar question (How to list kinds in datastore?), however it does not solve my problem as it is python specific.
I am currently using a GDS library in PHP (https://github.com/tomwalder/php-gds) that helps me fetch data from GDS if I know the Entity name using "SELECT * FROM Kind" GQL query.
I am currently in a situation where I may not know the name of the Entity KIND which I need to fetch data from hence the need to get the list of Entity KINDS which I can then look through and confirm if the entity exists, then run my select query.
Any pointers would be greatly appreciated.
Here's an alternate approach based on GQL... This returns a list of the Kinds available:
SELECT * FROM __kind__
In theory, you can then obtain the schema for this object by listing the associated properties for a given Kind (e.g., Person):
SELECT * FROM __property__
WHERE __key__ HAS ANCESTOR KEY(__kind__, 'Person')
If you are using Google's library to issue these queries, then you will have to set the AllowLiterals = true property in your request to avoid getting an exception with an error detail saying Disallowed literal: KEY.
Also, since the property_representation values are overloaded for things like Dates vs Integers, then you can only use the type data as a guess of the underlying type, possibly using conventions. As you cursor through the data, you could update the type information. It's curious that there isn't a better way since Google's Datastore UI provides type information when you create a new instance of an Entity.
You can query them Using the metadata objects of ndb.
https://cloud.google.com/appengine/docs/python/ndb/metadata#get_kinds

How to implement a server-side querying solution for mongo db references

I am relatively new to Mongo DB, but I am finding that is merges nicely with a project that I am working on. I am currently stuck at a problem however that I am really struggling to resolve...
This is specifically related to mongo db's "manual" references, documented here: http://docs.mongodb.org/manual/reference/database-references/#document-references
The project that I am working on sees every single document as a re-usable object instance, meaning that it can be embedded within another document, and because I am using manual references along with the client-side to resolve the references, it works really well. The issue arises when I want to be able to find objects, based on the value of one of the child objects.
A likely scenario:
we have an Orders collection which stores generated shop orders. An order object has a property named "products" which when viewed in mongo db is an array of references to product objects.
we also have a Products collection which stores products that can be used in orders.
say we want to be able to find all orders that contain the product "foo-bar", and bearing in mind that the path order.products is an array of references (not the embedded objects), what would be the most efficient way to do this? The most ideal solution would be the ability to simply use order.products.name : 'foo-bar'
A few additional notes:
fetching all order objects from the database and having the client-side resolve the objects to filter out the ones that we're looking for is far too inefficient.
embedding the product documents inside of the order documents is not an option, as it is essential to be able to modify the order and product documents independently of each other.
I am accessing mongo db using a PHP framework (and the official mongo db php extension)
a server-side solution would be ideal
I have briefly looked into the ability to write custom functions on mongo's server-side, but I can't quite tell if that would be a potential way to go?
Seems that you want to use joins (a term from SQL). Mongodb has no support for joins or alternative techniques.
The simplest thing that can work here is two-step query (pseudo-code)
product_ids = db.products.find(name: 'foo-bar').only('id')
orders = db.orders.find(product_id: {$in: product_ids})
This way you don't download a bunch of product objects onto the client, only their ids. It works quite well for me in my apps.
But this task is, of course, much better handled by a real relational DB.

multiple databases with same structure

What is the best way in doctrine2 to deal with different bases but with the same schema. Currently I
generate entities separately for every database, adding namespace and name of database to every metadata object, putting them in the different namespaces (XXX\Base\EntityClass), but with the same alias
create one EntityManager per base (even if they are sharing same connection)
create a proxy which passes calls to multiple EntityManagers and collects responses
merge responses in one output
Is there simpler way of dealing with multiple bases in doctrine2 ?
I can't answer for doctrine2, but I'm doing this in C#.
One set of entities, with strong names and strong types, defined in terms of what the rest of the application needs. This maps the schema, but isn't tied to either database.
One facade, the knows which database you're using at the moment, and directs requests to one of two...
Separate data access namespaces, that handle a common set of operations, and populate results into the single set of entities, which are returned to the requestor through the facade.
Static code generators, based on reading the scema from the database catalog, are useful. You may want to pick one as a model, if you can infer everything you need to know about the other database.
Dynamic code generators are also useful, for inserts, updates, where clauses, etc.
Invest some time in a framework to support all of this. Decide whether you need to keep metadata at run time, and whether it's primarily to support queries or change operations. Provide a common method for extracting data from results sets for either database, so that you can get strongly named and typed result sets back to your application without regard to the underlying database.

Categories