Tips for implementing pagination in a search result by adjusting the skip and limit values within the same query

While some may argue that this question belongs on programmers.stackexchange.com, after reviewing the Help Center of Stack Overflow, I believe it is a specific programming issue and will likely receive a better response here.

I have developed a webapp using ExpressJS with a Neo4j database backend. On the search screen, I want to leverage Neo4j's relationships. The screen allows users to input values such as manufacturing year, fuel type, gearbox, etc., which are then sent via POST request to ExpressJS where I construct a Cypher query based on these parameters. An example of the query is shown below:

MATCH
  (v:VEHICLE),(v)-[:VGEARBOX_IS]->(:VGBOX{type:'MANUAL'}),
  (v)-[:VCONDITION_IS]->(:VCONDITION{condition:'USED'})  
WITH DISTINCT v
WHERE  v.manufacture_year = 1990
MATCH (v)-[r]->(info)
RETURN v AS vehicle, COLLECT({type:type(r), data:info}) AS details

Running the above query returns information about three vehicles along with their properties.

https://i.stack.imgur.com/qBdvP.jpg

If there are more than 20 vehicles in the result, I would like to paginate the results using SKIP and LIMIT as shown below:

MATCH
  (v:VEHICLE)
OPTIONAL MATCH (v)-[r:VFUEL_TYPE|:VGEARBOX_IS|:VHAVING_COLOR|...]->(info)
RETURN
  v.vehicle_id AS vehicle_id,
  v.engine_size AS engine_size,
  v.published_date AS published_date,
  COUNT(v) AS count,
  COLLECT({type:type(r), data:info}) as data
ORDER BY v.published_date DESC
SKIP 20
LIMIT 16

The workflow for this process is as follows:

  • User navigates to the search screen form with various input fields using POST method.
  • User selects options to search based on their preferences.
  • User submits the form triggering a post request to the server.
  • This request is handled by a ROUTE which constructs a Cypher query using the request parameters and runs it against the Neo4j database to retrieve the results.
  • If there are 200 matching vehicles, only 20 are displayed, along with next/previous buttons for pagination.
  • To show additional results, the same query is rerun with an updated SKIP value.

My question is, what is the most optimal way to save the original search request or generated Cypher query so that clicking next/previous pages triggers a rerun using different SKIP values? I aim to avoid making fresh POST requests every time the user changes pages. There are several potential solutions, but I am unsure which is the most performance-friendly:

  1. Create a new POST request with preserved values each time the user clicks next/previous pages (I am concerned about the costliness of multiple POSTs).
  2. Store the original Cypher query in Redis and retrieve it when needed for pagination updates (handling deletion when necessary).
  3. Save the query in a session or temporary storage for quick access (security and efficiency concerns).

If you have encountered this issue before and found an efficient solution, please share your insights on how best to address this problem.

Answer №1

When it comes to optimizing performance, one of the key steps is utilizing Cypher parameters in your Neo4j queries. By separating the query string from dynamic data, you not only mitigate the risk of injection attacks but also enhance performance by allowing Neo4j to cache query plans for repeated use. An example of a query with parameters:

MATCH
  (v:VEHICLE),(v)-[:VGEARBOX_IS]->(:VGBOX{type: {vgearbox_type}}),
  (v)-[:VCONDITION_IS]->(:VCONDITION{condition: {vcondition}})  
WITH DISTINCT v
WHERE  v.manufacture_year = {manufacture_year}
MATCH (v)-[r]->(info)
RETURN v AS vehicle, COLLECT({type:type(r), data:info}) AS details
SKIP ({page} - 1) * {per_page}
LIMIT {per_page}

It's important that your javascript library allows passing a separate object down to Neo4j. This object, represented in json format, would contain specific values for the parameters used in the query.

{
  "vgearbox_type": "MANUAL",
  "vcondition": "USED",
  "manufacture_year": 1990,
  "page": 1,
  "per_page": 20
}

While querying the database from Node each time may not pose a significant issue, it's advisable to benchmark the process to determine any potential bottlenecks. Caching can be considered based on your server setup and proximity between the Node app and the DB. Redis caching or browser local storage for per-user basis caching are options, depending on data variability and user behavior.

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

What are some tips for utilizing markers that display location values in the format of a bar chart on Google Maps?

Hey there, I have a project in mind to create a Google map with markers representing specific locations and their values displayed as bar charts. Here is the code snippet from my index page: --index.html-- <!DOCTYPE html> <html> <head ...

Mobile display exhibiting glitches in animation performance

I have implemented an animation in the provided code snippet. const logo = document.querySelector('.logo'); const buttons = document.querySelectorAll('.loadclass'); const html = document.querySelector('html') const cornerme ...

Having trouble with ejs.filters?

I'm having trouble grasping ejs filters and getting them to work correctly: Server.js var ejs = require('ejs'); ejs.filters.example = function() { //placeholder for example }; Routes.js app.get('/home', function(req, res) { ...

invalid audio element

I'm currently working on building an audio player with a visualizer feature. However, when I try to initiate the audio player by clicking on the input button, my debug console keeps showing this error message: Uncaught (in promise) DOMException: Fa ...

Retrieving text content from multiple classes with a single click event

There are numerous elements each having class names p1, p2, p3,...p14. Consequently, when attempting to extract text from the clicked class, text from all classes is retrieved! For instance, if the expected text is 80, it ends up being 808080080808080808 ...

Using Node.js in combination with Express to render various views

Is there a way to send two consecutive ejs pages to the client with this code snippet: app.post('/', function(req,res) { res.render('yourDemandIsBeingProceed.ejs'); //some code which may take some time (such as running an external ...

Ways to conceal the header and footer on specific React pages

I currently have my header and footer wrapping the content on all pages of my website. However, I am looking to hide the header and footer on specific pages like the customer and admin dashboard. Can anyone suggest the best approach to achieve this? cons ...

Filtering tables in Angular 6 using checkbox options

I have a functional code snippet that filters a table using checkboxes. However, I am facing an issue when unchecking a checkbox. It does not return the original array as expected. .html <ng-container *ngFor="let group of groups"> <label cla ...

Can two writable stores in Svelte be set up to subscribe to each other simultaneously?

There is a unique scenario where two objects share data, yet have different structures. For instance, the 'Team' object has the team ID as its key. The 'Team' object includes 'name' and 'users' objects as its values ...

The PUT rest service does not function in AngularJS version 1.0.8

I am facing an issue with my AngularJS application that has a CRUD Rest service. While the Create, Read, and Delete methods are functioning properly, the PUT method is not working. I have searched on Stackoverflow and found similar problems with accepted s ...

Incorporating a module with the '@' symbol in a Node, Express, and Typescript environment

I recently started using Node and Typescript together. I came across a file where another module is imported like this import { IS_PRODUCTION } from '@/config/config';. I'm confused about how the import works with the @ symbol. I could real ...

Can you define the "tab location" in an HTML document using React?

Consider this component I have: https://i.stack.imgur.com/rAeHZ.png React.createClass({ getInitialState: function() { return {pg: 0}; }, nextPage: function(){ this.setState({ pg: this.state.pg+1} ) }, rend ...

Difficulty surfaced in the React project following relocation to a different device

I'm new to using React and webpack with babel loader in my app. My project was running smoothly until I changed machines. I copied all the files except for node_modules (which I installed with npm install). Now, when I try to run or build the projec ...

Toggle the opening and closing of React components with a map function using onclick

Implementing an onClick function within a map operation, I am encountering an issue where clicking the onClick button changes the state of all items in the map, instead of just the item clicked. This is being done using the useState hook. const [open, se ...

The functionality of the JavaScript animated placeholder seems to be malfunctioning

I am currently working on a code that updates the placeholder text every 2 seconds. The idea is to have it type out the letters one by one, and then erase them in the same manner. Unfortunately, the code is not functioning as expected. As a newcomer to J ...

Printing incorrect value in $.ajax call

I came across this code that I have been working on: var marcas = { nome: '', fipeId: '' }; var marcasVet = []; var select; $.ajax({ dataType: "json", url: 'http://fipeapi.wipsites.co ...

Displaying an element outside with reduced opacity using fabric js and controls placed above overlay

The property controlsAboveOverlay in Fabric.js is a boolean that, when set to true, will display the controls (borders, corners, etc.) of an object above the overlay image. The overlay image is an image that can be placed on top of the canvas. Currently, ...

Leveraging the withWidth higher order component (HOC) provided by

I am currently using version 3.9.2 of Material UI and experimenting with the withWidth HOC in a server-side rendered application. When I disable Javascript in the debugger options of Chrome Developer Tools, everything functions as expected by displaying t ...

Guide to placing a button on the same line as text with the use of JavaScript

Does anyone know how to add a button to the right of text that was added using JS DOM? I've tried multiple techniques but can't seem to get it right - the button always ends up on the next line. Any tips on how to achieve this? var text = docu ...

I'm encountering an issue where the JSON data I'm inserting into a pug template is adding "<" at the start of a string and ">" at the end. Can anyone explain why this is happening and how I can remove it?

Need help with JSON file and rendering in Express { "LunchItems": [ // List of lunch items with name, price, and description ] } I have a JSON file and using Express to render Pug files const express = require('express') ...