Optimize NeptuneDB Gremlin query - gremlin

vehicles --> accounts --> organizations <-- users
We have the above graph structure where vechicles , accounts, organizations and users are vertex labels and the arrows indicate the edge direction.
Consider the following number of vertices :
organizations = 1
accounts per organizations = 2
vehciles per account = 5000
users per organizations = 100
Our requirement is , given two vertexIds , find a set of all users and vehicles that satisfy the above graph.
For example if I have vertex1 = accounts:1 and vertex2 = organizations:1 , find the set of users and vehicles that are part of these two vertices.
We have the following query
g.V('accounts:1').outE().otherV().hasId('organizations:1')
.V('accounts:1').inE().otherV().as('B')
.V('organizations:1').inE().otherV().as('A')
.select('A', 'B')
While this works , the query takes ~3.5 seconds to complete , now we know that there are going to be 500000 traversers for this query.
Is there a better way to do this ?
Thanks for the help
Edit #1 : Attaching the query's profile API response
Optimized Traversal
===================
Neptune steps:
[
NeptuneGraphQueryStep(VertexId)#[A, B] {
JoinGroupNode {
JoinGroupNode {
PatternNode[(?1=<accounts:1>, <lifestate>, "ACTIVE", ?) . project ?1 .], {estimatedCardinality=1799504, expectedTotalOutput=1, indexTime=0, joinTime=1, numSearches=1, actualTotalOutput=1}
PatternNode[(?1, ?5, ?3=<organizations:1>, ?6) . project ?1,?6,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=102, expectedTotalOutput=1, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=1}
PatternNode[(?6, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=1, indexTime=0, joinTime=2, numSearches=1, actualTotalOutput=1}
PatternNode[(?3, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1, indexTime=0, joinTime=2, numSearches=1, actualTotalOutput=1}
}, finishers=[dedup(?3)]
PatternNode[(?8=<organizations:1>, <~label>, ?9, <~>) . project distinct ?8 .], {estimatedCardinality=INFINITY, expectedTotalOutput=1, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=1}
PatternNode[(?8, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=1}
PatternNode[(?10, ?12, ?8, ?13) . project ?8,?13,?10 . IsEdgeIdFilter(?13) .], {estimatedCardinality=INFINITY, expectedTotalOutput=102, indexTime=0, joinTime=1, numSearches=1, actualTotalOutput=102}
PatternNode[(?13, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=102, indexTime=0, joinTime=128, numSearches=102, actualTotalOutput=102}
PatternNode[(?13, <role>, "admin", ?) . project ask .], {estimatedCardinality=113376, expectedTotalOutput=100, indexTime=1, joinTime=6, numSearches=102, actualTotalOutput=100}
PatternNode[(?10, <~label>, ?14=<users>, <~>) . project ask .], {estimatedCardinality=2326404, expectedTotalOutput=100, indexTime=0, joinTime=128, numSearches=100, actualTotalOutput=100}
PatternNode[(?10, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=100, indexTime=0, joinTime=83, numSearches=100, actualTotalOutput=100}
PatternNode[(?10, <~label>, ?15=<users>, <~>) . project ?10 .], {estimatedCardinality=2326404, expectedTotalOutput=100, indexTime=1, joinTime=1, numSearches=1, actualTotalOutput=100}
PatternNode[(?16=<accounts:1>, <~label>, ?17, <~>) . project distinct ?16 .], {estimatedCardinality=INFINITY, expectedTotalOutput=100, indexTime=0, joinTime=1, numSearches=1, actualTotalOutput=100}
PatternNode[(?16, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=100, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=100}
PatternNode[(?18, ?20, ?16, ?21) . project ?16,?21,?18 . IsEdgeIdFilter(?21) .], {estimatedCardinality=INFINITY, expectedTotalOutput=1000, indexTime=0, joinTime=119, numSearches=1, actualTotalOutput=500000}
PatternNode[(?21, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=1000, indexTime=194, joinTime=142, numSearches=5000, actualTotalOutput=500000}
PatternNode[(?18, <~label>, ?22=<vehicles>, <~>) . project ask .], {estimatedCardinality=238260, expectedTotalOutput=1000, indexTime=183, joinTime=499, numSearches=5000, actualTotalOutput=500000}
PatternNode[(?18, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1000, indexTime=193, joinTime=858, numSearches=5000, actualTotalOutput=500000}
PatternNode[(?18, <~label>, ?23=<vehicles>, <~>) . project ?18 .], {estimatedCardinality=238260, indexTime=360, joinTime=1372, numSearches=500}
}, annotations={path=[Vertex(?1):GraphStep, Edge(?6):VertexStep, Vertex(?3):EdgeOtherVertexStep, Vertex(?8):GraphStep, Edge(?13):VertexStep, Vertex(?10):EdgeOtherVertexStep, VertexId(?10):IdStep#[A], Vertex(?16):GraphStep, Edge(?21):VertexStep, Vertex(?18):EdgeOtherVertexStep, VertexId(?18):IdStep#[B]], joinStats=true, optimizationTime=329, maxVarId=24, executionTime=6279}
},
NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [SelectStep(last,[A, B])]
WARNING: >> SelectStep(last,[A, B]) << (or one of its children) is not supported natively yet
Physical Pipeline
=================
NeptuneGraphQueryStep#[A, B]
|-- StartOp
|-- JoinGroupOp
|-- JoinGroupOp
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?1=<accounts:1>, <lifestate>, "ACTIVE", ?) . project ?1 .], {estimatedCardinality=1799504, expectedTotalOutput=1})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?1, ?5, ?3=<organizations:1>, ?6) . project ?1,?6,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=102, expectedTotalOutput=1})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?6, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=1})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?3, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1})
|-- FilterOp
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?8=<organizations:1>, <~label>, ?9, <~>) . project distinct ?8 .], {estimatedCardinality=INFINITY, expectedTotalOutput=1})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?8, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?10, ?12, ?8, ?13) . project ?8,?13,?10 . IsEdgeIdFilter(?13) .], {estimatedCardinality=INFINITY, expectedTotalOutput=102})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?13, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=102})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?13, <role>, "admin", ?) . project ask .], {estimatedCardinality=113376, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?10, <~label>, ?14=<users>, <~>) . project ask .], {estimatedCardinality=2326404, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?10, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?10, <~label>, ?15=<users>, <~>) . project ?10 .], {estimatedCardinality=2326404, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?16=<accounts:1>, <~label>, ?17, <~>) . project distinct ?16 .], {estimatedCardinality=INFINITY, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?16, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=100})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?18, ?20, ?16, ?21) . project ?16,?21,?18 . IsEdgeIdFilter(?21) .], {estimatedCardinality=INFINITY, expectedTotalOutput=1000})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?21, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=3341886, expectedTotalOutput=1000})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?18, <~label>, ?22=<vehicles>, <~>) . project ask .], {estimatedCardinality=238260, expectedTotalOutput=1000})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?18, <lifestate>, "ACTIVE", ?) . project ask .], {estimatedCardinality=1799504, expectedTotalOutput=1000})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?18, <~label>, ?23=<vehicles>, <~>) . project ?18 .], {estimatedCardinality=238260})
Runtime (ms)
============
Query Execution: 6283.262
Serialization: 2120.104
Traversal Metrics
=================
Step Count Traversers Time (ms) % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(VertexId)#[A, obje... 500000 500000 2502.636 41.43
NeptuneTraverserConverterStep 500000 500000 2580.098 42.71
SelectStep(last,[A, B]) 500000 500000 958.328 15.86
>TOTAL - - 6041.062 -
Predicates
==========
# of predicates: 37
WARNING: reverse traversal with no edge label(s) - .in() / .both() may impact query performance
Results
=======
Count: 500000
Output: <Removed for space>
Response serializer: application/vnd.gremlin-v3.0+gryo
Response size (bytes): 64,000,045
Index Operations
================
Query execution:
# of statement index ops: 15915
# of unique statement index ops: 15915
Duplication ratio: 1.0
# of terms materialized: 0
Serialization:
# of statement index ops: 0
# of terms materialized: 0

If possible always provide labels on traversal steps like in() and out(). Also, you do not need to specify inE().otherV() unless you need data from the edge. in() will suffice. As a first step I would try:
g.V('accounts:1').out(<labels>).hasId('organizations:1')
.V('accounts:1').in(<labels>).as('B')
.V('organizations:1').in(<labels>).as('A')
.select('A', 'B')
Where <labels> will be of the form in('works-with','knows').
Using edge labels, especially on the in steps can help a lot in some cases. I would start there as a first step. There are other rewrites that can be tried but this is a good first step.

Related

Gremlin union query takes long time to execute against Neptune DB

The following Gremlin query takes long time when you run using union clause. This is a common search query which is being used from many pages.
It works fine if you use it on entities with fewer nodes. However, if you use it to search for entities with higher number of nodes it times out from UI (after 30 secs).
I have to use containing as it searches as user starts typing (after 4 chars).
I am using AWS Neptune database with Python Gremlin.
It works for entities with 30k nodes.
It is timing out for entities with 200k+ nodes.
When I run these clauses separately it works fine, looks like union is taking long time.
g.V().hasLabel("org").union(
        has(T.id, containing("{searchtext}")),
        has("name", containing("{searchtext}")),
        has("tin", containing("{searchtext}")),
     where(in_("orgcode").has(T.id, containing("{searchtext}".upper())))).limit(10).dedup().project("id","name").by(__.id()).by("name").toList()
*******************************************************
Neptune Gremlin Profile
*******************************************************
Query String
==================
g.V().hasLabel("org").union(
has(T.id, containing("0000804415")),
has("name", containing("0000804415")),
has("tin", containing("0000804415")),
inE("orgcode").has(T.id, containing("0000804415"))).limit(10).dedup().project("id","name").by(__.id()).by("name")
Original Traversal
==================
[GraphStep(vertex,[]), HasStep([~label.eq(org)]), UnionStep([[HasStep([~id.containing(0000804415)]), EndStep], [HasStep([name.containing(0000804415)]), EndStep], [HasStep([tin.containing(0000804415)]), EndStep], [VertexStep(IN,[orgcode],edge), HasStep([~id.containing(0000804415)]), EndStep]]), RangeGlobalStep(0,10), DedupGlobalStep, ProjectStep([id, name],[[IdStep], value(name)])]
Optimized Traversal
===================
Neptune steps:
[
NeptuneGraphQueryStep(Vertex) {
JoinGroupNode {
PatternNode[(?1, <~label>, ?2=<org>, <~>) . project ?1 .], {indexTime=0, joinTime=166, numSearches=1}
}, annotations={path=[Vertex(?1):GraphStep], joinStats=true, optimizationTime=0, maxVarId=15, chunkSize=10, executionTime=16936}
},
NeptuneUnionStep {
NeptuneGraphQueryStep(Vertex) {
JoinGroupNode {
FilterByP(?1: containing(0000804415)) .
}, annotations={initialValues={?1=null}, executionTime=16936, path=[Vertex(?1):GraphStep], chunkSize=10, optimizationTime=0, maxVarId=15, joinStats=true}
},
NeptuneGraphQueryStep(Vertex) {
JoinGroupNode {
PatternNode[(?1, <name>, ?9, ?) . project ask . FilterByP(?9: containing(0000804415)) .], {indexTime=102, joinTime=4304, numSearches=205662}
}, annotations={initialValues={?1=null}, executionTime=16936, path=[Vertex(?1):GraphStep], chunkSize=10, optimizationTime=0, maxVarId=15, joinStats=true}
},
NeptuneGraphQueryStep(Vertex) {
JoinGroupNode {
PatternNode[(?1, <tin>, ?10, ?) . project ask . FilterByP(?10: containing(0000804415)) .], {indexTime=93, joinTime=4215, numSearches=205662}
}, annotations={initialValues={?1=null}, executionTime=16935, path=[Vertex(?1):GraphStep], chunkSize=10, optimizationTime=0, maxVarId=15, joinStats=true}
},
NeptuneGraphQueryStep(Edge) {
JoinGroupNode {
PatternNode[(?11, ?13=<orgcode>, ?1, ?14) . project ?1,?14 . IsEdgeIdFilter(?14) . FilterByP(?14: containing(0000804415)) .], {indexTime=331, joinTime=4847, numSearches=20567}
}, annotations={initialValues={?1=null}, executionTime=16935, path=[Vertex(?1):GraphStep, Edge(?14):VertexStep], chunkSize=10, optimizationTime=0, maxVarId=15, joinStats=true}
}
},
NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: RangeGlobalStep(0,10),
Neptune steps:
[
NeptuneMemoryTrackerStep
]
+ not converted into Neptune steps: DedupGlobalStep,ProjectStep([id, name],[[IdStep], value(name)]),
WARNING: >> [RangeGlobalStep(0,10), DedupGlobalStep] << (or one of the children for each step) is not supported natively yet
Physical Pipeline
=================
NeptuneGraphQueryStep
|-- StartOp
|-- JoinGroupOp
|-- SpoolerOp(10)
|-- DynamicJoinOp(PatternNode[(?1, <~label>, ?2=<org>, <~>) . project ?1 .])
NeptuneUnionStep
|-- BindingSetQueue
|-- JoinGroupOp
|-- FilterOp(FilterByP(?1: containing(0000804415)) .)
|-- BindingSetQueue
|-- JoinGroupOp
|-- SpoolerOp(10)
|-- DynamicJoinOp(PatternNode[(?1, <name>, ?9, ?) . project ask . FilterByP(?9: containing(0000804415)) .])
|-- BindingSetQueue
|-- JoinGroupOp
|-- SpoolerOp(10)
|-- DynamicJoinOp(PatternNode[(?1, <tin>, ?10, ?) . project ask . FilterByP(?10: containing(0000804415)) .])
|-- BindingSetQueue
|-- JoinGroupOp
|-- SpoolerOp(10)
|-- DynamicJoinOp(PatternNode[(?11, ?13=<orgcode>, ?1, ?14) . project ?1,?14 . IsEdgeIdFilter(?14) . FilterByP(?14: containing(0000804415)) .])
Runtime (ms)
============
Query Execution: 16936.285
Serialization: 0.085
Traversal Metrics
=================
Step Count Traversers Time (ms) % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(Vertex) 205662 205662 282.539 1.67
NeptuneUnionStep([[NeptuneGraphQueryStep(Vertex... 16653.466 98.33
NeptuneTraverserConverterStep 0.023 0.00
RangeGlobalStep(0,10) 0.003 0.00
NeptuneMemoryTrackerStep 0.006 0.00
DedupGlobalStep 0.004 0.00
ProjectStep([id, name],[[IdStep], value(name)]) 0.004 0.00
>TOTAL - - 16936.048 -
Predicates
==========
# of predicates: 201
Results
=======
Count: 0
Output: []
Response serializer: application/vnd.gremlin-v3.0+json
Response size (bytes): 216
Index Operations
================
Query execution:
# of statement index ops: 431892
# of unique statement index ops: 431892
Duplication ratio: 1.0
# of terms materialized: 910040
Serialization:
# of statement index ops: 0
# of terms materialized: 0
%%gremlin
First, you can get better details of the execution of the query on Neptune by using Neptune's Gremlin query explainer (versus the default TinkerPop explain() or profile() steps). To do this use %%gremlin profile when executing the query in a cell.
On to the query...
It's likely not the union() that is causing the issues here, but the use of containing(). Neptune does not maintain a substring index of string properties within the database. So using any of the Gremlin Text Predicates [1] will incur some sort of partial scan of all properties with the property key that you're using for those filters.
If you need to do these types of queries on a regular basis, it would beneficial to use Neptune's Full-Text-Search integration with OpenSearch [2].
[1] https://tinkerpop.apache.org/docs/current/reference/#a-note-on-predicates
[2] https://docs.aws.amazon.com/neptune/latest/userguide/full-text-search-cfn-create.html

How can I build a wordpress gutenberg multiple blocks plugin that support dynamic content

I am creating a custom Wordpress theme with a set of custom Gutenberg Blocks. Previously I had all the blocks work as separate plugins and I started combining them into a single plugin as I thought it would be easier to maintain and update. My old folder structure looked like this:
wp-content
|
+-- plugins
| |
| +-- dir 1
| | +-- build
| | +-- node_modules
| | +-- src
| | | +-- index.js (includes edit and save functions)
| |
| +-- dir 2
| | +-- build
| | +-- node_modules
| | +-- src
| | | +-- index.js (includes edit and save functions)
My new folder stucture looks like this (learned from this project: https://github.com/rmorse/multiple-blocks-plugin)
wp-content
|
+-- plugins
| |
| +-- multiple-blocks-plugin
| | |
| | +-- blocks
| | | |
| | | +-- dir 1
| | | | +-- build
| | | | +-- src
| | | | | +-- edit.js
| | | | | +-- index.js
| | | | | +-- save.js
| | | | +-- block.json
| | | |
| | | +-- dir 2
| | | | +-- build
| | | | +-- src
| | | | | +-- edit.js
| | | | | +-- index.js
| | | | | +-- save.js
| | | | +-- block.json
| | | |
| | | +-- dir 3
| | | | +-- build
| | | | +-- src
| | | | | +-- edit.js
| | | | | +-- index.js
| | | | +-- block.json
| | | | +-- index.php (the callback function is stored here)
| | |
| | +-- build
| | +-- node_modules
| | +-- multiple-blocks-plugin.php
Inside the multiple-blocks-plugin.php file, I maintain a list of all my plugins which I register using register_block_type() functions. These functions tell Wordpress to look for block.json files, where all my settings and attributes are now stored. One of my blocks is using dynamic content (a news block that should always show the latest three posts). My main problem is that I cannot get my new setup to read the callback_function when the function is stored inside the new folder structure. I aim to rebuild all my blocks to be dynamic, but I want to maintain a single plugin + multiple-block setup.
This is the function that registers all of the different blocks and the faulty one for /blocks/news/
function create_block_multiple_blocks_block_init()
{
register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-prices/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-services/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/column-block-specialists/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/counter/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/counter-list/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/cta-banner/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/gallery/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/gallery-image/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/image-text-block/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/hero/');
register_block_type_from_metadata(plugin_dir_path(__FILE__) . 'blocks/news/', array(
"callback_function" => "news_register_block"
));
register_block_type(plugin_dir_path(__FILE__) . 'blocks/opening-hours/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/opening-hours-list/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/process/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/process-list/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/why-choose-us/');
register_block_type(plugin_dir_path(__FILE__) . 'blocks/why-choose-us-list/');
}
add_action('init', 'create_block_multiple_blocks_block_init');
Question
How do I set up a project that uses dynamic blocks, where all blocks are stored inside a single plugin? I am quite new to Wordpress development - I am used to working in Sitecore - and I would love to learn how to best set up such a project. Thank you.
I'd use the DirectoryIterator to be as lazy as possible and scan that 'blocks' directory. Maybe I'd make it look if a block.json is present and then let it register this directory.
foreach ( $blocks = new DirectoryIterator( __DIR__ . '/blocks' ) as $item ) {
if ( $item -> isDir() && !$item -> isDot() ) if ( file_exists( $item -> getPathname() . '/block.json' ) ) register_block_type( $item -> getPathname() );
}
Next step could be that you include a php file that is named exactly like the folder. In that folder you store a name-of-the-folder_render_callback function. If said file is present, include it and use the name-of-the-folder_render_callback in the register_block_type args.
foreach ( $blocks = new DirectoryIterator( __DIR__ . '/blocks' ) as $item ) {
if ( $item -> isDir() && !$item -> isDot() ) if ( file_exists( $item -> getPathname() . '/block.json' ) ) {
if ( file_exists( $item -> getPathname() . '/' . $item -> getBasename() . '.php' ) ) {
include( $item -> getPathname() . '/' . $item -> getBasename() . '.php' );
register_block_type( $item -> getPathname() , array( 'render_callback' => $item -> getBasename() . '_render_callback' ) );
} else {
register_block_type( $item -> getPathname() );
}
}
}
Untested, though.

WordPress ENV / WP_HOME / WP_SITE_URL

I'm struggling to find the cause of this issue and hoping someone can point me in the right direction.
A few parts are based on roots, but I can't seem to find any answers over they to do with this.
Here is the file structure -> http://imgur.com/a/W2eYY
What seems to go on is when I go to go through the installation/setup of WordPress and enter this into the URL (framework(.)dev/public/wp/) it changes itself to this (http://framework.dev/public/wp/framework.dev/wp/wp-admin/install.php) is there any way to just make it goes to (framework(.)dev/wp/wp-admin/install.php)
Key
(.) = .
Won't let me post more than 2 links
.env file:
BB_USER=BBUSERNAME
DB_NAME=framework
DB_USER=root
DB_PASSWORD=root
DB_HOST=localhost
DB_PREFIX=wp_
WP_ENV=Development
WP_HOME=framework.dev
WP_SITEURL=${WP_HOME}/wp
composer.json:
{
"name": "framework/framework",
"description": "Modern WordPress Framework",
"type": "wordpress-core",
"authors": [
{
"name": "Name",
"email": "name#gmail.com"
}
],
"config": {
"preferred-install": "dist"
},
"repositories":[
{
"type":"composer",
"url":"https://wpackagist.org"
}
],
"scripts": {
"post-install-cmd": [
"cp -r public/wp/wp-content public/app"
]
},
"require": {
"php": ">=5.6",
"composer/installers": "1.3.0",
"johnpbloch/wordpress": "4.8.0",
"roots/wp-password-bcrypt": "1.0.0",
"timber/timber": "1.3.2",
"roots/soil": "3.7.2",
"mnsami/composer-custom-directory-installer": "1.1.1",
"vlucas/phpdotenv": "2.4.0",
"oscarotero/env": "^1.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "^2.5.1"
},
"extra": {
"installer-paths": {
"public/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
"public/app/plugins/{$name}/": ["type:wordpress-plugin"],
"public/app/themes/{$name}/": ["type:wordpress-theme"]
},
"wordpress-install-dir": "public/wp"
}
}
config/application.php
<?php
/** #var string Directory containing all of the site's files */
$root_dir = dirname(__DIR__);
/** #var string Document Root */
$webroot_dir = $root_dir . '/public';
/*
|------------------------------------------------------------------
| Expose global ENV
|------------------------------------------------------------------
|
| Expose global env() function from oscarotero/env
|
*/
Env::init();
/*
|------------------------------------------------------------------
| Dotenv Settings
|------------------------------------------------------------------
|
| Use Dotenv to set required environment variables and load .env file in root
|
*/
$dotenv = new Dotenv\Dotenv($root_dir);
if (file_exists($root_dir . '/.env')) {
$dotenv->load();
$dotenv->required(['DB_NAME', 'DB_USER', 'DB_PASSWORD', 'WP_HOME', 'WP_SITEURL']);
}
/*
|------------------------------------------------------------------
| ENV Settings
|------------------------------------------------------------------
|
| Set up our global environment constant and load its config first
| Default: Development
|
*/
define('WP_ENV', env('WP_ENV') ?: 'production');
$env_config = __DIR__ . '/environments/' . WP_ENV . '.php';
if (file_exists($env_config)) {
require_once $env_config;
}
/*
|------------------------------------------------------------------
| URL
|------------------------------------------------------------------
|
| Env's for the URL
|
*/
define('WP_HOME', env('WP_HOME'));
define('WP_SITEURL', env('WP_SITEURL'));
/*
|------------------------------------------------------------------
| Custom Content Directory
|------------------------------------------------------------------
|
| Changes where the content is stored.
|
*/
define('CONTENT_DIR', '/app');
define('WP_CONTENT_DIR', $webroot_dir . CONTENT_DIR);
define('WP_CONTENT_URL', WP_HOME . CONTENT_DIR);
/*
|------------------------------------------------------------------
| DB Settings
|------------------------------------------------------------------
|
| Uses ENV to populate the correct DB settings.
|
*/
define('DB_NAME', env('DB_NAME'));
define('DB_USER', env('DB_USER'));
define('DB_PASSWORD', env('DB_PASSWORD'));
define('DB_HOST', env('DB_HOST'));
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
$table_prefix = env('DB_PREFIX');
/*
|------------------------------------------------------------------
| Authentication Unique Keys and Salts
|------------------------------------------------------------------
|
| Automatically Generated by the init setup command
|
*/
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');
/*
|------------------------------------------------------------------
| Custom Settings
|------------------------------------------------------------------
|
| Custom Global Settings that won't be affected by the ENV
|
*/
define('AUTOMATIC_UPDATER_DISABLED', true);
define('DISABLE_WP_CRON', env('DISABLE_WP_CRON') ?: false);
define('DISALLOW_FILE_EDIT', true);
define ('WPLANG', 'en_GB');
/*
|------------------------------------------------------------------
| Roots/soil Settings
|------------------------------------------------------------------
|
| Include any number of roots/soil options here
|
*/
// add_theme_support('soil-clean-up');
// add_theme_support('soil-disable-trackbacks');
// add_theme_support('soil-relative-urls');
/*
|------------------------------------------------------------------
| Bootstrap WordPress
|------------------------------------------------------------------
|
| Bootstrap WordPress
|
*/
if (!defined('ABSPATH')) {
define('ABSPATH', $webroot_dir . '/wp/');
}
public/index.php
<?php
define('WP_USE_THEMES', true);
require( dirname( __FILE__ ) . '/wp/wp-blog-header.php' );
public/wp-config.php
<?php
require_once(dirname(__DIR__) . '/vendor/autoload.php');
require_once(dirname(__DIR__) . '/config/application.php');
require_once(ABSPATH . 'wp-settings.php');
wp-cli.yml
path: public/wp
Add http:// to your WP_HOME env variable.
This seems to work.
WP_HOME=http://example.dev/public
WP_SITEURL=${WP_HOME}/wp/

Reduce network traffic for Native Client installation from Chrome Web Store

My Chrome app contains three .nexe files for arm, x86-32 and 64-bit processors. When I install this app from Chrome web store, the size of downloaded package is the same as the size of the app containing all .nexe files. Is it possible to optimize this network traffic?
My .nmf file bundled in the app looks like this:
{
"program": {
"arm": { "url": "arm.nexe" },
"x86-32": { "url": "x86_32.nexe" },
"x86-64": { "url": "x86_64.nexe" }
}
}
Thanks
Yes, you can add a platform specific section to your manifest.json. Then the packages will only download the components that are specified for that CPU architecture.
There is documentation for that feature here: https://developer.chrome.com/native-client/devguide/distributing#reducing-the-size-of-the-user-download-package
And there is an example in the SDK as well: examples/tutorial/multi_platform
To summarize the documentation above:
First create a _platform_specific directory in your App package. For each architecture, create a subdirectory with that name:
|-- my_app_directory/
| |-- manifest.json
| |-- my_app.html
| |-- my_module.nmf
| +-- css/
| +-- images/
| +-- scripts/
| |-- _platform_specific/
| | |-- x86-64/
| | | |-- my_module_x86_64.nexe
| | |-- x86-32/
| | | |-- my_module_x86_32.nexe
| | |-- arm/
| | | |-- my_module_arm.nexe
| | |-- all/
| | | |-- my_module_x86_64.nexe
| | | |-- my_module_x86_64.nexe
| | | |-- my_module_x86_32.nexe
Then in the manifest.json file, specify the location of these directories:
...
"platforms": [
{
"nacl_arch": "x86-64",
"sub_package_path": "_platform_specific/x86-64/"
},
{
"nacl_arch": "x86-32",
"sub_package_path": "_platform_specific/x86-32/"
},
{
"nacl_arch": "arm",
"sub_package_path": "_platform_specific/arm/"
},
{
"sub_package_path": "_platform_specific/all/"
}
]
You'll want your .nmf to point to the location of these nexes. The SDK build system has an option to do all of this for you automatically, I'd suggest using it.

Virtuoso Dump graph

Hello I have a probably simple problem but I am not able to find it anywhere in docs.
I use this code in Virtuoso Interactive SQL:
SPARQL clear graph <http://product-open-data.org/temp>;
SPARQL clear graph <http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01>;
DB.DBA.TTLP ('
#prefix rr: <http://www.w3.org/ns/r2rml#> .
#prefix foaf: <http://xmlns.com/foaf/0.1/> .
#prefix gr: <http://purl.org/goodrelations/v1#> .
#prefix s: <http://schema.org/> .
#prefix pod: <http://linked.opendata.cz/ontology/product-open-data.org#>
<#TriplesMapBrand>
a rr:TriplesMap;
rr:logicalTable [
rr:tableSchema "POD";
rr:tableOwner "DBA";
rr:tableName "BRAND"
];
rr:subjectMap
[
rr:template "http://linked.opendata.cz/resource/brand/{BSIN}";
rr:class gr:Brand;
rr:graph <http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01>
];
rr:predicateObjectMap [
rr:predicateMap [rr:constant pod:bsin];
rr:objectMap [rr:termType rr:Literal; rr:column "BSIN" ];
];
rr:predicateObjectMap [
rr:predicateMap [rr:constant gr:name];
rr:objectMap [rr:termType rr:Literal; rr:column "BRAND_NM" ];
];
rr:predicateObjectMap [
rr:predicateMap [rr:constant s:url];
rr:objectMap [rr:termType rr:IRI; rr:template "{BRAND_LINK}";];
];.
', 'http://product-open-data.org/temp', 'http://product-open-data.org/temp', 0);
exec ('sparql ' || DB.DBA.R2RML_MAKE_QM_FROM_G ('http://product-open-data.org/temp','http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01'));
SPARQL Select * from <http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01>
where {?s ?o ?p.} limit 1000000;
My problem is following: I want to get a TTL file with dump_one_graph procedure. But when I run the procedure like this in iSQL:
SQL> DB.DBA.dump_one_graph('http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01','../R2RML/pod_',1000000000);
the only thing I get is:
Dump of graph http://linked.opendata.cz/resource/dataset/product-open-data.org/2014-01-01, as of 2014-11-11 23:46:48.000004
So my question is: where are my triples stored and why is SPARQL SELECT returning a result set while dump_one_graph doesn't?
R2RML gets mapped to Virtuoso RDFViews which are not persisted to the Quad Store by default.
There is an option to make these material or persisted to the Quad Store.
Have a look at: r2rml. There should by an option 'Enable Data Syncs with Physical Quad Store' which should do the trick. Also have a look at the Generate RDB2RDF triggers option. I don't know exactly how this will look with turtle-syntax, but you can inspect the resulting commands by using the 'Prepare to Execute Button.
Hope this helps...

Resources