@@ -73,40 +73,38 @@ const job3 = db.mergeNode(
7373 discoveredAt : new Date ( ) . toISOString ( ) ,
7474 applicationStatus : 'not_applied' ,
7575 viewCount : 0
76- } ,
76+ } as any ,
7777 onMatch : {
7878 lastSeenAt : new Date ( ) . toISOString ( )
7979 // viewCount would be incremented here in real app
80- }
80+ } as any
8181 }
8282) ;
8383
8484console . log ( 'First merge (CREATE):' ) ;
8585console . log ( ` Created: ${ job3 . created } ` ) ;
86- console . log ( ` discoveredAt: ${ job3 . node . properties . discoveredAt } ` ) ;
87- console . log ( ` applicationStatus: ${ job3 . node . properties . applicationStatus } ` ) ;
88- console . log ( ` lastSeenAt: ${ job3 . node . properties . lastSeenAt || 'undefined' } \n` ) ;
86+ console . log ( ` discoveredAt: ${ ( job3 . node . properties as any ) . discoveredAt } ` ) ;
87+ console . log ( ` applicationStatus: ${ ( job3 . node . properties as any ) . applicationStatus } ` ) ;
88+ console . log ( ` lastSeenAt: ${ ( job3 . node . properties as any ) . lastSeenAt || 'undefined' } \n` ) ;
8989
90- // Wait a bit then merge again
91- setTimeout ( ( ) => {
92- const job4 = db . mergeNode (
93- 'Job' ,
94- { url : 'https://example.com/job/456' } ,
95- undefined ,
96- {
97- onMatch : {
98- lastSeenAt : new Date ( ) . toISOString ( ) ,
99- viewCount : ( job3 . node . properties . viewCount || 0 ) + 1
100- }
90+ // Immediately merge again to demonstrate MATCH behavior
91+ const job4 = db . mergeNode (
92+ 'Job' ,
93+ { url : 'https://example.com/job/456' } ,
94+ undefined ,
95+ {
96+ onMatch : {
97+ lastSeenAt : new Date ( ) . toISOString ( ) ,
98+ viewCount : ( ( job3 . node . properties as any ) . viewCount || 0 ) + 1
10199 }
102- ) ;
100+ } as any
101+ ) ;
103102
104- console . log ( 'Second merge (MATCH):' ) ;
105- console . log ( ` Created: ${ job4 . created } ` ) ;
106- console . log ( ` discoveredAt: ${ job4 . node . properties . discoveredAt } (preserved)` ) ;
107- console . log ( ` lastSeenAt: ${ job4 . node . properties . lastSeenAt } (updated)` ) ;
108- console . log ( ` viewCount: ${ job4 . node . properties . viewCount } (incremented)\n` ) ;
109- } , 100 ) ;
103+ console . log ( 'Second merge (MATCH):' ) ;
104+ console . log ( ` Created: ${ job4 . created } ` ) ;
105+ console . log ( ` discoveredAt: ${ ( job4 . node . properties as any ) . discoveredAt } (preserved)` ) ;
106+ console . log ( ` lastSeenAt: ${ ( job4 . node . properties as any ) . lastSeenAt } (updated)` ) ;
107+ console . log ( ` viewCount: ${ ( job4 . node . properties as any ) . viewCount } (incremented)\n` ) ;
110108
111109// ============================================================================
112110// Example 3: Company Deduplication
@@ -150,12 +148,12 @@ const edge1 = db.mergeEdge(
150148 {
151149 onCreate : { firstSeenAt : new Date ( ) . toISOString ( ) } ,
152150 onMatch : { lastVerifiedAt : new Date ( ) . toISOString ( ) }
153- }
151+ } as any
154152) ;
155153
156154console . log ( `First edge merge: Created=${ edge1 . created } ` ) ;
157- console . log ( ` firstSeenAt: ${ edge1 . edge . properties ?. firstSeenAt } ` ) ;
158- console . log ( ` lastVerifiedAt: ${ edge1 . edge . properties ?. lastVerifiedAt || 'undefined' } ` ) ;
155+ console . log ( ` firstSeenAt: ${ ( edge1 . edge . properties as any ) ?. firstSeenAt } ` ) ;
156+ console . log ( ` lastVerifiedAt: ${ ( edge1 . edge . properties as any ) ?. lastVerifiedAt || 'undefined' } ` ) ;
159157
160158// Second merge: Finds existing relationship
161159const edge2 = db . mergeEdge (
@@ -165,12 +163,12 @@ const edge2 = db.mergeEdge(
165163 undefined ,
166164 {
167165 onMatch : { lastVerifiedAt : new Date ( ) . toISOString ( ) }
168- }
166+ } as any
169167) ;
170168
171169console . log ( `\nSecond edge merge: Created=${ edge2 . created } ` ) ;
172- console . log ( ` firstSeenAt: ${ edge2 . edge . properties ?. firstSeenAt } (preserved)` ) ;
173- console . log ( ` lastVerifiedAt: ${ edge2 . edge . properties ?. lastVerifiedAt } (updated)\n` ) ;
170+ console . log ( ` firstSeenAt: ${ ( edge2 . edge . properties as any ) ?. firstSeenAt } (preserved)` ) ;
171+ console . log ( ` lastVerifiedAt: ${ ( edge2 . edge . properties as any ) ?. lastVerifiedAt } (updated)\n` ) ;
174172
175173// ============================================================================
176174// Example 5: Bulk Import with Merge (Idempotent ETL)
@@ -191,43 +189,42 @@ const scrapedJobs = [
191189let created = 0 ;
192190let matched = 0 ;
193191
194- db . transaction ( ( ) => {
195- for ( const jobData of scrapedJobs ) {
196- // Merge company
197- const company = db . mergeNode (
198- 'Company' ,
199- { name : jobData . company } ,
200- { name : jobData . company }
201- ) ;
202-
203- // Merge job with tracking
204- const job = db . mergeNode (
205- 'Job' ,
206- { url : jobData . url } ,
207- {
208- url : jobData . url ,
209- title : jobData . title ,
210- status : 'active'
192+ // Note: Each merge operation has its own transaction, so we don't need to wrap
193+ for ( const jobData of scrapedJobs ) {
194+ // Merge company
195+ const company = db . mergeNode (
196+ 'Company' ,
197+ { name : jobData . company } ,
198+ { name : jobData . company }
199+ ) ;
200+
201+ // Merge job with tracking
202+ const job = db . mergeNode (
203+ 'Job' ,
204+ { url : jobData . url } ,
205+ {
206+ url : jobData . url ,
207+ title : jobData . title ,
208+ status : 'active'
209+ } ,
210+ {
211+ onCreate : {
212+ discoveredAt : new Date ( ) . toISOString ( ) ,
213+ applicationStatus : 'not_applied'
211214 } ,
212- {
213- onCreate : {
214- discoveredAt : new Date ( ) . toISOString ( ) ,
215- applicationStatus : 'not_applied'
216- } ,
217- onMatch : {
218- lastSeenAt : new Date ( ) . toISOString ( ) ,
219- status : 'active' // Reactivate if was closed
220- }
215+ onMatch : {
216+ lastSeenAt : new Date ( ) . toISOString ( ) ,
217+ status : 'active' // Reactivate if was closed
221218 }
222- ) ;
219+ } as any
220+ ) ;
223221
224- // Merge relationship
225- db . mergeEdge ( job . node . id , 'POSTED_BY' , company . node . id ) ;
222+ // Merge relationship
223+ db . mergeEdge ( job . node . id , 'POSTED_BY' , company . node . id ) ;
226224
227- if ( job . created ) created ++ ;
228- else matched ++ ;
229- }
230- } ) ;
225+ if ( job . created ) created ++ ;
226+ else matched ++ ;
227+ }
231228
232229console . log ( `Processed ${ scrapedJobs . length } scraped jobs:` ) ;
233230console . log ( ` ${ created } new jobs created` ) ;
@@ -281,22 +278,20 @@ console.log('======================================\n');
281278
282279const iterations = 1000 ;
283280
284- // Manual pattern
281+ // Manual pattern (with transaction per operation for fair comparison)
285282const manualStart = Date . now ( ) ;
286283for ( let i = 0 ; i < iterations ; i ++ ) {
287- db . transaction ( ( ) => {
288- const existing = db
289- . nodes ( 'TestNode' )
290- . where ( { key : `test-${ i % 100 } ` } )
291- . limit ( 1 )
292- . exec ( ) [ 0 ] ;
293-
294- if ( existing ) {
295- db . updateNode ( existing . id , { updated : true } ) ;
296- } else {
297- db . createNode ( 'TestNode' , { key : `test-${ i % 100 } ` , created : true } ) ;
298- }
299- } ) ;
284+ const existing = db
285+ . nodes ( 'TestNode' )
286+ . where ( { key : `test-${ i % 100 } ` } )
287+ . limit ( 1 )
288+ . exec ( ) [ 0 ] ;
289+
290+ if ( existing ) {
291+ db . updateNode ( existing . id , { updated : true } as any ) ;
292+ } else {
293+ db . createNode ( 'TestNode' , { key : `test-${ i % 100 } ` , created : true } as any ) ;
294+ }
300295}
301296const manualTime = Date . now ( ) - manualStart ;
302297
@@ -312,8 +307,8 @@ for (let i = 0; i < iterations; i++) {
312307 db . mergeNode (
313308 'TestNode' ,
314309 { key : `test-${ i % 100 } ` } ,
315- { key : `test-${ i % 100 } ` , created : true } ,
316- { onMatch : { updated : true } , warnOnMissingIndex : false }
310+ { key : `test-${ i % 100 } ` , created : true } as any ,
311+ { onMatch : { updated : true } , warnOnMissingIndex : false } as any
317312 ) ;
318313}
319314const mergeTime = Date . now ( ) - mergeStart ;
0 commit comments