# -*- tcl -*- # # An example for using MongoDB as a persistence store. # # Gustaf Neumann fecit, Feb 2014 # package require nx::mongo package require nx::serializer package require nx::test #nsf::configure debug 2 ###################################################################### # Define sample methods to use MongoDB as a simple persistence store # for nx. The provided methods are # # nx::Class "mongo persist" ?-db db? ?-collection name? ?-closure? # nx::Class "mongo fetch" ?-db db? ?-collection name? # # where "mongo persist" stores/updates the direct or indirect # instances in the specified collection and "mongo fetch" loads # all instances from this collection # nx::Class public method "mongo persist" { {-db "tutorial"} {-collection "nx"} {-closure:switch} } { set mongo_ns $db.$collection set count(update) 0 set count(insert) 0 foreach i [:info instances -closure=$closure] { set isNew [string match "::nsf::__#*" $i] set bson [list name string $i class string [$i info class] isNew string $isNew] lappend bson definition string [$i serialize] if {[::nx::var exists $i _id]} { #puts "we have to update " ::nx::mongo::db update $mongo_ns [list _id oid [::nx::var set $i _id]] $bson incr count(update) } else { #puts "we have to insert to $mongo_ns" set r [::nx::mongo::db insert $mongo_ns $bson] ::nx::var set $i _id [lindex $r 2] incr count(insert) } } puts "$count(insert) instances inserted, $count(update) instances updated in $mongo_ns" } nx::Class public method "mongo fetch" { {-db "tutorial"} {-collection "nx"} } { set mongo_ns $db.$collection set result {} set bson [::nx::mongo::db query $mongo_ns {}] foreach obj $bson { foreach {att type value} $obj { switch $att { _id {set _id $value} class {set class $value} definition {set definition $value} name {set name $value} } } eval $definition $name eval [list set _id $_id] ::nx::var set $name _id $_id lappend result $name } return $result } # ###################################################################### # # Sample usage of the two methods # # Establish connection to the database ::nx::mongo::db connect -db "tutorial" # Make sure, we start always from scratch, so remove everything from # the collection. nx::mongo::db drop collection nx ###################################################################### # # Define an arbitrary class # nx::Class create Foo { :property title :property {count 1} :public method ++ {} {incr :count} :public method hasArray {} {array exists :a} :public object method counts {} { foreach i [:info instances] {incr c [$i cget -count]} return $c } :public object method countArrays {} { foreach i [:info instances] {incr c [$i hasArray]} return $c } } ###################################################################### # # Create an instance of Foo containing e.g. arrays or dicts as # instance variables # Foo new -title t1 { set :a(1) a set :a(2) b set :d [dict create x 100 y 101] set :count 100 } Foo new -title t2 ? {llength [Foo info instances]} 2 "Foo instances before persist" ? {Foo counts} 101 ? {Foo countArrays} 1 foreach i [Foo info instances] {$i ++} ? {Foo counts} 103 # # Save all instances of Foo (inserts) # Foo mongo persist # # Destroy all instances of Foo in memory # foreach i [Foo info instances] {$i destroy} ? {llength [Foo info instances]} 0 "Foo instances after destroy" # # Load instances from MongoDB # ::nx::Class mongo fetch ? {llength [Foo info instances]} 2 "Foo instances after fetch" ? {Foo counts} 103 ? {Foo countArrays} 1 foreach i [Foo info instances] {$i ++} ? {Foo counts} 105 # # create one more instance, also with an array # Foo new {set :a(x) foo} ? {Foo counts} 106 ? {Foo countArrays} 2 # # Save all instances of Foo (updates) # Foo mongo persist foreach i [Foo info instances] {$i destroy} ? {llength [Foo info instances]} 0 "Foo instances after destroy" ::nx::Class mongo fetch ? {Foo counts} 106 ? {Foo countArrays} 2 ###################################################################### # # Local variables: # mode: tcl # tcl-indent-level: 2 # indent-tabs-mode: nil # End: