@@ -5404,6 +5404,139 @@ the results of your queries as JSON. Remember that if you do save an entire grap
5404
5404
JSON, unless you specify otherwise, the default format is GraphSON 3.0 with
5405
5405
embedded types.
5406
5406
5407
+
5408
+ [[nulls]]
5409
+ Using null in Gremlin
5410
+ ~~~~~~~~~~~~~~~~~~~~~
5411
+
5412
+ Gremlin does allow null values to move through a traversal. Whether or not nulls are
5413
+ meaningful to you with Gremlin tends to depend on the graph database that you are
5414
+ using and whether or not it supports storing null values. If the graph does not
5415
+ support that capability, then you won't encounter a null in your traversal pipeline
5416
+ or your results unless you introduce the null value yourself. You might do that by
5417
+ way of a side-effect or some other Gremlin step that allows you to supply a value to
5418
+ the stream. The following examples demonstrate a few ways that you might choose to
5419
+ do this:
5420
+
5421
+ [source,groovy]
5422
+ ----
5423
+ g.inject(null)
5424
+
5425
+ null
5426
+
5427
+ g.V().limit(10).coalesce(has('elev',gt(3000)), constant(null)).fold()
5428
+
5429
+ [null,v[2305],null,null,null,null,v[2300],null,v[2308],v[2307]]
5430
+ ----
5431
+
5432
+ The prior examples don't showcase any particular common use case and unless the graph
5433
+ itself supports storing null values there is little foundation for injecting them in
5434
+ this fashion. For graphs that do support storing null, such as TinkerGraph, you can
5435
+ treat nulls in much the same manner that you do other values in Gremlin.
5436
+
5437
+ NOTE: TinkerGraph is not configured to support null storage by default. You must
5438
+ provide set the 'gremlin.tinkergraph.allowNullPropertyValues' to true in its
5439
+ configuration to enable it.
5440
+
5441
+ Before we look too closely at how null is used in a graph that supports it, let's
5442
+ first take a look at what happens with null for graphs that do not. In particular,
5443
+ we should look at the 'property' step.
5444
+
5445
+ [source,groovy]
5446
+ ----
5447
+ g.addV('airport').property('code',null)
5448
+
5449
+ v[41223]
5450
+
5451
+ g.V().has('code',null)
5452
+
5453
+ // no result
5454
+
5455
+ g.V().hasNot('code')
5456
+
5457
+ v[41223]
5458
+ ----
5459
+
5460
+ NOTE: For better portability, prefer 'drop' when removing properties.
5461
+
5462
+ In the prior example, Gremlin semantics expect that calls to 'property' with a null
5463
+ value assignment will result in the step being ignored if the property does not exist
5464
+ or removed if it does. The following demonstrates the latter:
5465
+
5466
+ [source,groovy]
5467
+ ----
5468
+ g.addV('airport').property('code','XYZ')
5469
+
5470
+ v[41224]
5471
+
5472
+ g.V(41224).property('code',null)
5473
+
5474
+ v[41224]
5475
+
5476
+ g.V().hasNot('code')
5477
+
5478
+ v[41224]
5479
+ ----
5480
+
5481
+ Now that we've looked at graphs that don't support null, let's look at how Gremlin
5482
+ behaves for those that do:
5483
+
5484
+ [source,groovy]
5485
+ ----
5486
+ g.addV('airport').property('code',null)
5487
+
5488
+ v[41228]
5489
+
5490
+ g.V().has('code',null)
5491
+
5492
+ v[41228]
5493
+
5494
+ g.V().has('code',within('IAD',null)).values('code')
5495
+
5496
+ null
5497
+ IAD
5498
+ ----
5499
+
5500
+ As you can see in the prior example, the null value is being stored in and retrieved
5501
+ from the graph. By electing to use this feature, you now have the additional burden
5502
+ of accounting for null in your query. Gremlin steps tend to behave in null-safe ways
5503
+ as shown in the the following examples:
5504
+
5505
+ [source,groovy]
5506
+ ----
5507
+ g.V().has('code',within('IAD',null)).values('code').substring(0,1).fold()
5508
+
5509
+ [null,I]
5510
+
5511
+ g.V().has('code',within('IAD',null)).values('code').length().fold()
5512
+
5513
+ [null,3]
5514
+
5515
+ g.V().has('code',within('IAD',null)).values('code').groupCount()
5516
+
5517
+ [null:1,IAD:1]
5518
+
5519
+ g.V().has('code',within('IAD',null)).values('code').order()
5520
+
5521
+ null
5522
+ IAD
5523
+
5524
+ g.V().has('code',within('IAD',null)).values('code').order().by(desc)
5525
+
5526
+ IAD
5527
+ null
5528
+ ----
5529
+
5530
+ The choice to use null is often made for you as many graphs do not support storing
5531
+ nulls at which point injecting them yourself into your queries doesn't tend to
5532
+ provide much added value. In addition, when the graph you are using does support it,
5533
+ you should take care in the choice to use it because it will reduce the portability
5534
+ of your application by limiting your graph choices as you will have to find another
5535
+ that also supports the feature. On the flip side, if you choose a graph that does not
5536
+ support null values and use the 'property('key' ,null)' syntax to remove properties,
5537
+ then keep in mind that this syntax will behave quite differently if you switch to a
5538
+ graph that suddenly supports storing nulls!
5539
+
5407
5540
[[traversal-strategies]]
5408
5541
Understanding TraversalStrategies
5409
5542
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 commit comments