Mistakes encountered when utilizing the Gremlin DSL in the `repeat` stage

Our team is utilizing gremlin-javascript and has recently implemented a DSL (Domain Specific Language) to streamline our queries.

However, we have encountered an issue when trying to use DSL methods within a repeat step. Every time we attempt this, we consistently get "

(...).someDslFunction is not a function
" errors. Interestingly, using the same DSL function outside of the repeat block works perfectly fine.

Below is a simplified DSL definition that showcases this problem:

class CustomDSLTraversal extends GraphTraversal {
  constructor(graph, traversalStrategies, bytecode) {
    super(graph, traversalStrategies, bytecode);
  }

  hasNotLabel(...args) {
    return this.not(__.hasLabel(...args));
  }

  filterNotLabel(...args) {
    return this.filter(__.hasNotLabel(...args));
  }
}

class CustomDSLTraversalSource extends GraphTraversalSource {
  constructor(graph, traversalStrategies, bytecode) {
    super(graph, traversalStrategies, bytecode, CustomDSLTraversalSource, CustomDSLTraversal);
  }
}

const statics = {
  hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
  ...gremlin.process.statics
};

const __ = statics;
const g = traversal(CustomDSLTraversalSource).withRemote(connection);

Here are two instances where this issue arises - the first one functions as expected, while the second triggers "

__.outE().(...).filterNotLabel is not a function
" error.

g.V('foo').outE().filterNotLabel('x', 'y').otherV(); // No errors
g.V('foo').repeat(__.outE().filterNotLabel('x', 'y').otherV()).times(1); // Error

// __.outE(...).filterNotLabel is not a function

EDIT: A member of our team pointed out a possible solution:

The issue stemmed from redefining callOnEmptyTraversal for usage with our DSL, while mistakenly integrating standard TinkerPop anonymous traversals into our custom ones. As a result, the original callOnEmptyTraversal was employed, which utilizes an instance of the base GraphTraversal.

function callOnEmptyTraversal(fn, args) {
  const g = new CustomDSLTraversal(null, null, new Bytecode());
  return g[fn].apply(g, args);
}

const statics = {
  hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
  mapToObject: (...args) => callOnEmptyTraversal('mapToObject', args),
  ...gremlin.process.statics // Oops
};

const __ = statics;

SOLUTION: To address this issue and merge our DSL anonymous traversal spawns with the standard TinkerPop ones, I made the following adjustment:

function callOnEmptyTraversal(fn, args) {
  const g = new CustomDSLTraversal(null, null, new Bytecode());
  return g[fn].apply(g, args);
}

function mapToCallOnEmptyTraversal(s, fn) {
  s[fn] = (...args) => callOnEmptyTraversal(fn, args);
  return s;
}

const statics = ['hasNotLabel', 'mapToObject']
 .concat(Object.keys(gremlin.process.statics))
 .reduce(mapToCallOnEmptyTraversal, {});

const __ = statics;

Answer №1

It seems like the issue lies in starting your traversal with __, which is the standard TinkerPop spawn for anonymous traversals. This results in a GraphTraversal being created instead of your desired CustomDSLTraversalSource. According to the TinkerPop gremlin-javascript documentation:

steps that are available on a GraphTraversal should also be accessible as spawns for anonymous traversals

To rectify this, you may need to create your own version of __ that returns the CustomDSLTraversalSource. For a more detailed insight into where things might be going wrong, check out this section of the code where callOnEmptyTraversal() returns a GraphTraversal and consequently your DSL methods won't be available on that class.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The error message "TypeError: Cannot set property 'href' of undefined" occurred at angular.js line 12520 when trying to set $window.location.href

Has anyone tried using a directive function to redirect when clicking with ng-click? Here is the HTML code: <a ng-click="navbarlinksCtrl.clickedfr()" ng-class="{active: clickedfr()}">FR</a><br> <a ng-click="navbarlinksCtrl.clickeden( ...

Guide to utilizing an Ajax response object

Here is the code I am using to display data based on values selected from dropdowns: $("#botao-filtrar").click(function(){ $(".mask-loading").fadeToggle(1000); $.ajax({ url: 'datacenter/functions/filtraDashboardGeral.php', as ...

Identifying CMYK Images Through Javascript Feature Detection

Many are aware that IE8 does not support CMYK JPG images, as it fails to render them at all. This post discusses the issue further: , among others. My inquiry is as follows: Is there a method to detect from JavaScript, akin to Modernizr, whether a browse ...

Guide to dynamically inserting an audio file into a div with jQuery

I am looking to dynamically insert an audio file. Below are the declared tags: <div> <audio id="myaudio"> </audio> </div> Now, I am trying to add the source dynamically. Can anyone help me with how to add it to the div or audi ...

Hosting a WCF service in a virtual directory on a shared hosting environment

In the midst of my work on a next js project, I encountered the need to invoke a wcf service. To rectify an error caused by the secure server hosting the site, necessitating the service also be hosted securely, I resorted to creating a virtual directory ...

Ways to incorporate various styles on a mobile screen for a javascript-generated function

In my current project, I have implemented a JavaScript function that renders HTML within a module. function generateHTML(bankName) { let content = `<div class="bankName" style=""><strong style="font-size: 28px;font-wei ...

Receiving the outcome of an asynchronous function in JavaScript

async function retrieveKey() { try { var key = await dec.awsDecrypt('dev-frontend') return key; } catch(err) { } } //calling the function const result = retrieveKey() In the code snippet above, there is an asynchronous ...

Disappear button once all elements have been added to the array - utilizing redux

I currently have a list of locations with the option to add them all to another array using an 'ADD all button'. The adding functionality works perfectly, but I now need to hide the 'ADD all button' after it has been clicked. So far, I ...

Rendering elements dynamically using ng-repeat following an AJAX request

Feeling frustrated, I made an $http request ApiService.get_request_params("api/endpoint").then( function(data) { $scope.customers = data }, function(err) { } ); The $scope.customers should be bound to an ng-repeat. I can see the ...

Tips for loading a unique class name on the initial active UI react component

Is there a way to load a class named "Landingpage" to the body tag or main container div only when the first tab/section (Overview page) is active? The tab sections are located in a child component. Any assistance would be appreciated. Click here for more ...

What is the best way to divide middleware within feathers?

I have been using the multer library with feathers to upload files. In my effort to separate logic from code, I have decided to move the upload functionality from the index.js file to a new file named pdf.js within the middleware directory. Below is the c ...

Karma jasmine and an angular controller that utilizes the 'Controller as' syntax (where 'this' is used instead of $scope)

I'm having trouble setting up karma for my unit tests, specifically on a basic example: Here is the controller file: angular.module('balrogApp.requests', [ /* Dependencies */ ]) // Routes configuration .config(['$routeProvider&a ...

Steps to assign the user id where the isDisliked field is not true

I'm struggling to populate the user from the likedBy field where isDisliked is false. Can you please refer to the document schema https://i.sstatic.net/jb8x8.png for more information? Although I've tried using the query below, I can't seem ...

Modifying and replacing content in a local file using JavaScript

I have a file located in a directory called testfolder on my local disk. The contents of the file are as follows: Apples are red. <colour = red/> latitude 13.124165 Would it be possible to retrieve the content of this file, store it in a variable, ...

Beginner coding exercises to master JavaScript

With a proficiency in CSS, HTML, and some knowledge of Jquery and PHP, I aspire to become a Front End Web Developer. However, my lack of understanding in Javascript is holding me back. I acquired my current skillset by rapidly learning over 9 months while ...

Why does event.touches on iPad sometimes show as undefined?

I'm encountering a problem with my code which controls a slider on an iPad. The issue seems to stem from the fact that ev.originalEvent.touches is sometimes returning undefined... Does anyone have any insights into what might be causing this? I' ...

What is the best way to refresh or render a list in a React application?

While attempting to update the calendar days by using useState, I encountered a "too many re-renders" error. Even though the list was updated correctly, the component did not render on the screen as expected. I am struggling with figuring out how to update ...

Interactions of selecting dates in datepicker widget

Currently, I am working on developing my personal work website. One issue I have encountered is with the calendar feature. The "From" date can be selected before today's date, which is not ideal. Additionally, if a date 5 days from now is chosen as th ...

Running Angular without dependencies causes it to malfunction

I recently ventured into the world of AngularJS and started by creating a module without any services or factories. Everything was running smoothly until I decided to introduce services and factories into my code. Suddenly, things stopped working. Here is ...

An array of size 10x10 where each new array replaces the previous one

I'm currently working on a function that generates a 10 by 10 array filled with random D's and E's. Below is the code snippet: function generateTenByTenArray(){ var outerArray = []; var innerArray = []; for(var i = 0; i < 10 ...