14

Is there a way to return just an integer through cypher?

I am working with neo4j and the javascript driver. However when I do a count() I get {low: 10, high: 0}. I would like to force this to return a low integer instead of the object above. Is this possible through cypher?

Note that I don't want to do this in the neo4j javascript driver and prefer to do this in cypher since I know it will be a low number...

Terence Chow
  • 10,755
  • 24
  • 78
  • 141

5 Answers5

12

Starting from 1.6 version of the driver it is possible to configure it to only return native numbers instead of custom Integer objects. The configuration option affects all integers returned by the driver. Enabling this option can result in a loss of precision and incorrect numeric values being returned if the database contains integer numbers outside of the range [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER].

var driver = neo4j.driver(
  'neo4j://localhost',
  neo4j.auth.basic('neo4j', 'neo4j'),
  { disableLosslessIntegers: true }
)

Source: https://github.com/neo4j/neo4j-javascript-driver#a-note-on-numbers-and-the-integer-type

Keep in mind that MAX_SAFE_INTEGER is 2^53-1 = 9,007,199,254,740,991

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
pawansgi92
  • 1,065
  • 13
  • 32
11

Cypher only works with Long and Double values. Javascript isn't able to adequately represent 64-bit Longs.

There's advice here from the Neo4j javascript driver for handling this when providing parameters to Neo4j queries, as well as for handling returned longs.

InverseFalcon
  • 29,576
  • 4
  • 38
  • 51
  • 3
    Yes, I saw that. But is there a way to force neo4j to use Double values so that they appear in JS as ints? It's quite tedious to have to write bespoke JS logic every time I have a query that uses integers. – Terence Chow Mar 07 '17 at 10:45
5

Use neo4j.integer.toNumber. So basically when you want to represent such value, use something like

variable.toNumber()

You will get a good old int value.

EliuX
  • 11,389
  • 6
  • 45
  • 40
  • This answer is wrong. See accepted answer. Neo4j works with 64-bit integers. Converting these to JavaScript representation without any check (for example neo4j.integer.inSafeRange) may lead to loss of precision. See https://www.npmjs.com/package/neo4j-driver section Reading integers for more information. – jmeinlschmidt Mar 10 '23 at 10:14
3

You can write your simple handler for the transformation:

var transformIntegers = function(result) {
  return new Promise( (resolve,reject) => {
    try {
      result.records.forEach( function(row, i) {
        row._fields.forEach( function(val, j) {
          result.records[i]._fields[j] = neo4j.isInt(val) 
              ? (neo4j.integer.inSafeRange(val) ? val.toNumber() : val.toString()) 
              : val;
        })
      })
      resolve(result);
    } catch (error) {
        reject( error );
    }
  });
};

And as an example:

session
  .run('MATCH (A) RETURN ID(A) AS id, toInteger(10^20) as unsafe LIMIT 1')
  .then( transformIntegers )
  .then( function(result) {
    console.log(result.records[0]);
    session.close();
    driver.close();
  })
  .catch( function(error) {
    console.log(error);
  });
stdob--
  • 28,222
  • 5
  • 58
  • 73
0

In constructor of my object, I'm using this function found here to convert to JS-friendly number. Works great so far!

function toNumber({ low, high }) {
  let res = high

  for (let i = 0; i < 32; i++) {
    res *= 2
  }

  return low + res
}
DurkoMatko
  • 5,238
  • 4
  • 26
  • 35