Add Edges collection to a graph - php

Using Arangodb 3.2, have a set of collections (arangoimp + CSV):
user (documents)
profile (documents)
user_profile (edges)
I'd like create a graph from listed above. Was unable to find in the documentation about composing graph from already existent collections of vertices and edges, or didn't get how to.
In [1] there is an example how to add relation (e.g. create edges collection, linking vertices), but what if I already have one?
It would be nice to understand how to compose a graph from existent collections via (AND/OR):
PHP (triagens/arangodb)
HTTP API
Bash
Links:
https://docs.arangodb.com/3.2/Manual/Graphs/GeneralGraphs/

Have you tried to create the graph via the web interface (https://docs.arangodb.com/devel/Manual/Administration/WebInterface/Graphs.html)?
If you want to create the graph just once this is an easy solution.

Finally I found a PHP solution myself:
$edgeDefinition = new \triagens\ArangoDb\EdgeDefinition(
'user_profile',
'user',
'profile'
);
$graphName = 'testGraph';
$graph = new \triagens\ArangoDb\Graph($graphName);
$graph->addEdgeDefinition($edgeDefinition);
$graphHandler = new \triagens\ArangoDb\GraphHandler($connection);
if (!$graphHandler->getGraph($graphName)) {
$graphHandler->createGraph($graph);
}
I'd propose update official docs (see [1]) with more explicit explanation of graph_module._relation parameters.
It's a pity, but there is no ArangoDb HTTP API solution yet.

Related

How to use PHP client for Google Custom Search Engine

I'm feeling like this is an idiotic mistake on my part, but I can't figure out how to use the google-api-php-client to do a simple search. My goal is to run simple keyword queries against a google search engine for my site.
I've created my api key, a google search engine and downloaded a release of the api client, but the google site for the php client doesn't seem to have any documentation on how to use the client and the only related example I've found so far specifically searches google's book service. The problem is that example implies that different search services have different search result types and I can't find any documentation on how to retrieve results from a Google_Service.
I think I can set up a simple search like this, but I don't know how to actually retrieve the results.
include_once __DIR__ . '/vendor/autoload.php';
...
public function __construct($searchTerm) {
$client = new Google_Client();
$client->setApplicationName("My_First_Search");
$client->setDeveloperKey(self::GCSE_API_KEY);
$service = new Google_Service($client);
$optParams = array('filter' => $searchTerm);
$results = $service->???
The documentation must be out there, but it's not in any of the obvious places....
Update (1/14/17):
(Update 1/21/17: actually, these docs didn't help me much, but I'll leave them up just FYI)
I used phpdoc to generate api documentation for the google apiclient. I made a repo and put the phpdocs and the libary on github. The phpdocs are browsable here.
So hopefully that will be helpful to someone. Unfortunately even with the docs I'm having trouble unraveling proper usage. I haven't generated docs for the google apiclient-services package yet because they are huge, but I can do that if necessary (depending on disk limits on github pages).
Thanks to #gennadiy for putting me on the right track. Without his suggestion to use ->cse->listCse() to retrieve the results, I probably would have given up and gone in search of a different library. Luckily this is pretty much all I need to use this library for so I think I'm all set.
Simple Example
Executing a search is pretty simple; it basically looks like this:
include_once __DIR__ . '/vendor/autoload.php';
$GCSE_API_KEY = "nqwkoigrhe893utnih_gibberish_q2ihrgu9qjnr";
$GCSE_SEARCH_ENGINE_ID = "937592689593725455:msi299dkne4de";
$client = new Google_Client();
$client->setApplicationName("My_App");
$client->setDeveloperKey($GCSE_API_KEY);
$service = new Google_Service_Customsearch($client);
$optParams = array("cx"=>self::GCSE_SEARCH_ENGINE_ID);
$results = $service->cse->listCse("lol cats", $optParams);
The results object implements Iterator so we can loop over them as follows:
foreach($results->getItems() as $k=>$item){
var_dump($item);
}
Google Prerequisites
In order to use this library though, you will have to set up a few google things first. These things are eventually mentioned on the Google API Client Libraries PHP (Beta) website, but you'll have to click around & dig for them and even then, you'll miss the last one below:
You will need a Custom Search Engine. Don't be confused by the fact that most of the references on the internet to Custom Search Engines are for people who are not trying to do programatic searches. You need one, and they're easy to set up here: https://cse.google.com/cse/all
You will need a Google Project. Again, set up is easy when you know where to go: https://console.developers.google.com/apis/dashboard
You will need an API Key (aka a Developer Key). Go here and create a new key if you don't already have one: https://console.developers.google.com/apis/credentials
You will need to enable Google Custom Search for your project. At this point you can make queries to google, but you may get an error response back if you have not yet enabled Google Custom Search for your project. Go to the dashboard, click the blue "Enable API" link, search for Google Custom Search and enable it. https://console.developers.google.com/apis/dashboard
A Thoroughly Commented Example
This is a more realistic example than the example above. It is still very simple, but it's always nice to have something new explained in two different ways with lots of explanatory comments.
<?php
include_once __DIR__ . '/vendor/autoload.php';
/**
* Retrieves a simple set of google results for a given plant id.
*/
class GoogleResults implements IteratorAggregate {
// Create one or more API keys at https://console.developers.google.com/apis/credentials
const GCSE_API_KEY = "nqwkoigrhe893utnih_gibberish_q2ihrgu9qjnr";
/* The search engine id is specific to each "custom search engine"
* you have configured at https://cse.google.com/cse/all
* Remember that you must have enabled Custom Search API for the project that
* contains your API Key. You can do this at the following url:
* https://console.developers.google.com/apis/api/customsearch.googleapis.com/overview?project=vegfetch-v01&duration=PT1H
* If you fail to enable the Custom Search API before you try to execute a search
* the exception that is thrown will indicate this. */
const GCSE_SEARCH_ENGINE_ID = "937592689593725455:msi299dkne4de";
// Holds the GoogleService for reuse
private $service;
// Holds the optParam for our search engine id
private $optParamSEID;
/**
* Creates a service object for our Google Custom Search. The API key is
* permiently set, but the search engine id may be changed when performing
* searches in case you want to search across multiple pre-prepared engines.
*
* #param string $appName Optional name for this google search
*/
public function __construct($appName = "My_Search") {
$client = new Google_Client();
// application name is an arbitrary name
$client->setApplicationName($appName);
// the developer key is the API Key for a specific google project
$client->setDeveloperKey(self::GCSE_API_KEY);
// create new service
$this->service = new Google_Service_Customsearch($client);
// You must specify a custom search engine. You can do this either by setting
// the element "cx" to the search engine id, or by setting the element "cref"
// to the public url for that search engine.
//
// For a full list of possible params see https://github.com/google/google-api-php-client-services/blob/master/src/Google/Service/Customsearch/Resource/Cse.php
$this->optParamSEID = array("cx"=>self::GCSE_SEARCH_ENGINE_ID);
}
/**
* A simplistic function to take a search term & search options and return an
* array of results. You may want to
*
* #param string $searchTerm The term you want to search for
* #param array $optParams See: For a full list of possible params see https://github.com/google/google-api-php-client-services/blob/master/src/Google/Service/Customsearch/Resource/Cse.php
* #return array An array of search result items
*/
public function getSearchResults($searchTerm, $optParams = array()){
// return array containing search result items
$items = array();
// Merge our search engine id into the $optParams
// If $optParams already specified a 'cx' element, it will replace our default
$optParams = array_merge($this->optParamSEID, $optParams);
// set search term & params and execute the query
$results = $this->service->cse->listCse($searchTerm, $optParams);
// Since cse inherits from Google_Collections (which implements Iterator)
// we can loop through the results by using `getItems()`
foreach($results->getItems() as $k=>$item){
var_dump($item);
$item[] = $item;
}
return $items;
}
}
You have to use not Google_Service, but Google_Service_Customsearch
$service = new Google_Service_Customsearch($client);
and then:
$results = $service->cse->listCse($searchTerm, $optParams);
The listCse() function (now) only takes one parameter - the complete array of keys mentioned in the API documentation (https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list).
So - a minimum the cx and q keys have to be included in the array.

FOSElasticaBundle: Is it possible to change "query_builder_method" in controller?

According to FOSElasticaBundle documentation it is possible to configure application to use custom query builder method like this:
user:
persistence:
elastica_to_model_transformer:
query_builder_method: createSearchQueryBuilder
But is it possible to choose QB method live, e.g. in controller action?
I'd like to be able to control what's being fetched from DB while transforming Elastica results to Doctrine entities. E.g. sometimes I'll want to do eager fetch on some relations, but can't do that by default.
Since FOSElasticaBundle documentation is not very precise, I went through its code and found it impossible to control what query builder is used on controller level.
It is possible to change whole elastica_to_model_transformer to a custom service, but still it's statically defined in configuration. Maybe with some dirty solution it would be possible going this way, but I don't think it's worth it.
I decided to just not using this feature of FOSElasticaBundle. The main problem I had was that when you use fos_elastica.index instead of fos_elastica.finder or elastica repository (in order to get plain not transformed results Elastica\Resultset), there's no findPaginated method with returns Pagerfanta paginator object, which is very helpful in my case.
Fortunately although it's not mentioned in documentation it's possible to create the Pagerfanta this way too, but a little bit more manually.
Here's a code snippet:
//generate ElaticaQuery somehow.
$browseQuery = $browseData->getBrowseQuery();
$search = $this->container->get('fos_elastica.index.indexName.typName');
//create pagerfanta's adapter manually
$adapter = new \Pagerfanta\Adapter\ElasticaAdapterElasticaAdapter($search, $browseQuery);
// now you can create the paginator too.
$pager = new Pagerfanta($adapter);
//do some paging work on it...
$pager->setMaxPerPage($browseData->getPerPage());
try {
$pager->setCurrentPage($browseData->getPage());
} catch(OutOfRangeCurrentPageException $e) {
$pager->setCurrentPage(1);
}
//and get current page results.
/** #var Result[] $elasticaResults */
$elasticaResults = $pager->getCurrentPageResults();
// we have to grab ids manyally, but it's done the same way inside FOSElasticaBundle with previous approach
$ids = array();
foreach($elasticaResults as $elasticaResult) {
$ids[] = $elasticaResult->getId();
}
//use regular Doctrine's repository to fetch Entities any way you want.
$entities = $this->getDoctrine()->getRepository(MyEntity::class)->findByIdentifiers($ids);
This actually has a few advantages. In general it gives you back control over your data and doesn't tie ElasticSearch with Doctrine. Therefore you can resign on fetching data from Doctrine if you have all needed data in ElasticSearch (if they are read only data of course). This lets you optimize your application performance but reducing amount of SQL queries.
The code above may be wrapped with some kind of service in order to prevent making mess in controllers.

Use nested transformers in Laravel 5

In my Laravel 5 app, I'm implementing Transformers and Fractal.
I've got in my example two different models: User and UserLogin. Every User can have multiple UserLogins (I've already added a one-to-many relationship between them). Now I want to "clean" my response, which returns an User with his UserLogins. So I've created two transformers, and I thought that I should call a transformer inside the other one inside his return, like here:
"UserLogins"=> Fractal::collection($user->userLogins, new UserLoginTransformer).......
Unfortunately it doesn't work and the error is that it doesn't find fractal library (which is correctly imported).
What could be the problem?
Finally found the solution.
Fractal class does not exists, I cannot make simplier than that.
And you weren't correctly using the library.
So, the solution :
use \League\Fractal\Manager;
use \League\Fractal\Resource\Collection as FractalCollection;
$fractal = new Manager();
$resource = new FractalCollection($user->userLogins, new UserLoginTransformer);
return $fractal->createData($resource)->toArray();

how to build a comment tree using neo4j and PHP

I want to build a comment tree using neo4j and PHP for example:
A
|_B
...|_C
...|_D
I am using https://github.com/jadell/neo4jphp component. It doesnt heve this method. Anyway I dont know how to get all tree using Cypher.
You just add comments onto other comments, you can execute this cypher with neo4jphp or neoclient.
MATCH (c:Comment {id:{comment_id}})
MATCH (a:Author {id:{author_id}})
CREATE (n:Comment {id:{new_comment_id}, text:{new_comment_text})
CREATE (a)-[:WROTE]->(n)

What is the most efficient way to include an API on a page?

The website I am re-building uses its own API to gather most of its content (e.g. http://api.example.com/). Although the answer to this is quite self explanatory, I just want to be sure before I proceed.
As far as I am aware, I have 2 (potentially 3) options of loading the data from the api via PHP.
I can load the classes into the document and gather the data manually from the class (probably the best way, but requires more code and if changes are made to the class, I have to alter the pages and the API document instead of just changing the API)
Use file_get_contents('http://api.example.com/search'). This would be the easiest way but it requires another HTTP request and I assume it is slightly slower.
Lastly, if this this possible then I think it will be the best way, but to my knowledge I do not think it is possible. Read the file locally with $_GET parameters implemented and obtain the results this way.
EXAMPLES
1.
// Include the mysql connections
require_once($_SERVER['DOCUMENT_ROOT'].'/scripts/php/_connections/mysql.company.php');
// Include the Classes (Company and Facebook)
require_once($_SERVER['DOCUMENT_ROOT'].'/scripts/php/_classes/class.company.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/scripts/php/_classes/class.mysql.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/scripts/php/_facebook/config.facebook.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/scripts/php/_facebook/class.facebook.php');
// Create the objects (Company, MySQL, Memcache and Facebook)
$memcache = new memcache;
$facebook = new Facebook($facebook_config);
$mysql = new mysql($memcache);
$company = new company($_DATABASES,$_CONNECTIONS,$mysql,$memache,$facebook);
// CALL THE RELEVANT CLASS METHOD HERE
2.
Something like (ignore mistakes)
$API = 'http://api.example.com/search?query=test'
$data = file_get_contents(url_encode($API));
3.
Not sure if this is possible, please note I do NOT want to use the last method
$parameters = array(
'method'=>'GET',
'parameters'=>array(
'function'=>'search',
'query'=>'test'
)
);
$API = some_cool_function('/_scripts/api/2/api/api.php',$parameters);
// I DO NOT WANT TO DO THIS FOR CERTAIN REASONS:
$_GET=array(
'function'=>'search',
'query'=>'test'
);
$data = include('/_scripts/api/2/api/api.php');
Normally I'd say the 1st option - with Oauth etc that's in place in most API's these days I'm sure a nicely wrapped class setup would be much easier to work with.

Categories