github.com/altipla-consulting/ravendb-go-client@v0.1.3/readme.old.md (about) 1 2 [![Linux build Status](https://travis-ci.org/ravendb/ravendb-go-client.svg?branch=master)](https://travis-ci.org/ravendb/ravendb-go-client) [![Windows build status](https://ci.appveyor.com/api/projects/status/rf326yoxl1uf444h/branch/master?svg=true)](https://ci.appveyor.com/project/ravendb/ravendb-go-client/branch/master) 3 4 This is information on how to use the library. For docs on working on the library itself see [readme-dev.md](readme-dev.md). 5 6 This library requires go 1.11 or later. 7 8 API reference: https://godoc.org/github.com/altipla-consulting/ravendb-go-client 9 10 This library is in beta state. All the basic functionality works and passes extensive [test suite](/tests), but the API for more esoteric features might change. 11 12 If you encounter bugs, have suggestions or feature requests, please [open an issue](https://github.com/altipla-consulting/ravendb-go-client/issues). 13 14 ## Documentation 15 16 To learn basics of RavenDB, read [RavenDB Documentation](https://ravendb.net/docs/article-page/4.1/csharp) or [Dive into RavenDB](https://demo.ravendb.net/). 17 18 ## Getting started 19 20 Full source code of those examples is in `examples` directory. 21 22 To run a a specific example, e.g. `crudStore`, you can run: 23 * `.\scripts\run_example.ps1 crudStore` : works on mac / linux if you have powershell installed 24 * `go run examples\log.go examples\main.go crudStore` : on mac / linux change paths to `examples/log.go` etc. 25 26 1. Import the package 27 ```go 28 import ( 29 ravendb "github.com/altipla-consulting/ravendb-go-client" 30 ) 31 ``` 32 33 2. Initialize document store (you should have one DocumentStore instance per application) 34 ```go 35 func getDocumentStore(databaseName string) (*ravendb.DocumentStore, error) { 36 serverNodes := []string{"http://live-test.ravendb.net"} 37 store := ravendb.NewDocumentStore(serverNodes, databaseName) 38 if err := store.Initialize(); err != nil { 39 return nil, err 40 } 41 return store, nil 42 } 43 ``` 44 45 3. Open a session and close it when done 46 ```go 47 session, err = store.OpenSession() 48 if err != nil { 49 log.Fatalf("store.OpenSession() failed with %s", err) 50 } 51 // ... use session 52 session.Close() 53 ``` 54 55 4. Call `SaveChanges()` to persist changes in a session: 56 ```go 57 var e *northwind.Employee 58 err = session.Load(&e, "employees/7-A") 59 if err != nil { 60 log.Fatalf("session.Load() failed with %s\n", err) 61 } 62 63 origName := e.FirstName 64 e.FirstName = e.FirstName + "Changed" 65 err = session.Store(e) 66 if err != nil { 67 log.Fatalf("session.Store() failed with %s\n", err) 68 } 69 70 err = session.SaveChanges() 71 if err != nil { 72 log.Fatalf("session.SaveChanges() failed with %s\n", err) 73 } 74 75 var e2 *northwind.Employee 76 err = session.Load(&e2, "employees/7-A") 77 if err != nil { 78 log.Fatalf("session.Load() failed with %s\n", err) 79 } 80 fmt.Printf("Updated Employee.FirstName from '%s' to '%s'\n", origName, e2.FirstName) 81 ``` 82 See `loadUpdateSave()` in [examples/main.go](examples/main.go) for full example. 83 84 ## CRUD example 85 86 ### Storing documents 87 ```go 88 product := &northwind.Product{ 89 Name: "iPhone X", 90 PricePerUnit: 999.99, 91 Category: "electronis", 92 ReorderLevel: 15, 93 } 94 err = session.Store(product) 95 if err != nil { 96 log.Fatalf("session.Store() failed with %s\n", err) 97 } 98 ``` 99 See `crudStore()` in [examples/main.go](examples/main.go) for full example. 100 101 102 ### Loading documents 103 104 ```go 105 var e *northwind.Employee 106 err = session.Load(&e, "employees/7-A") 107 if err != nil { 108 log.Fatalf("session.Load() failed with %s\n", err) 109 } 110 fmt.Printf("employee: %#v\n", e) 111 ``` 112 See `crudLoad()` in [examples/main.go](examples/main.go) for full example. 113 114 ### Loading documents with includes 115 116 Some entities point to other entities via id. For example `Employee` has `ReportsTo` field which is an id of `Employee` that it reports to. 117 118 To improve performance by minimizing number of server requests, we can use includes functionality to load such linked entities. 119 120 ```go 121 // load employee with id "employees/7-A" and entity whose id is ReportsTo 122 var e *northwind.Employee 123 err = session.Include("ReportsTo").Load(&e, "employees/5-A") 124 if err != nil { 125 log.Fatalf("session.Load() failed with %s\n", err) 126 } 127 if e.ReportsTo == "" { 128 fmt.Printf("Employee with id employees/5-A doesn't report to anyone\n") 129 return 130 } 131 132 numRequests := session.GetNumberOfRequests() 133 var reportsTo *northwind.Employee 134 err = session.Load(&reportsTo, e.ReportsTo) 135 if err != nil { 136 log.Fatalf("session.Load() failed with %s\n", err) 137 } 138 if numRequests != session.GetNumberOfRequests() { 139 fmt.Printf("Something's wrong, this shouldn't send a request to the server\n") 140 } else { 141 fmt.Printf("Loading e.ReportsTo employee didn't require a new request to the server because we've loaded it in original requests thanks to using Include functionality\n") 142 } 143 ``` 144 See `crudLoadWithInclude()` in [examples/main.go](examples/main.go) for full example. 145 146 ### Updating documents 147 148 ```go 149 // load entity from the server 150 var p *northwind.Product 151 err = session.Load(&p, productID) 152 if err != nil { 153 log.Fatalf("session.Load() failed with %s\n", err) 154 } 155 156 // update price 157 origPrice = p.PricePerUnit 158 newPrice = origPrice + 10 159 p.PricePerUnit = newPrice 160 err = session.Store(p) 161 if err != nil { 162 log.Fatalf("session.Store() failed with %s\n", err) 163 } 164 165 // persist changes on the server 166 err = session.SaveChanges() 167 if err != nil { 168 log.Fatalf("session.SaveChanges() failed with %s\n", err) 169 } 170 ``` 171 See `crudUpdate()` in [examples/main.go](examples/main.go) for full example. 172 173 ### Deleting documents 174 175 Delete using entity: 176 177 ```go 178 // ... store a product and remember its id in productID 179 180 var p *northwind.Product 181 err = session.Load(&p, productID) 182 if err != nil { 183 log.Fatalf("session.Load() failed with %s\n", err) 184 } 185 186 err = session.Delete(p) 187 if err != nil { 188 log.Fatalf("session.Delete() failed with %s\n", err) 189 } 190 191 err = session.SaveChanges() 192 if err != nil { 193 log.Fatalf("session.SaveChanges() failed with %s\n", err) 194 } 195 196 ``` 197 See `crudDeleteUsingEntity()` in [examples/main.go](examples/main.go) for full example. 198 199 Entity must be a value that we either stored in the database in the current session via `Store()` 200 or loaded from database using `Load()`, `LoadMulti()`, query etc. 201 202 Delete using id: 203 204 ```go 205 // ... store a product and remember its id in productID 206 207 err = session.DeleteByID(productID, "") 208 if err != nil { 209 log.Fatalf("session.Delete() failed with %s\n", err) 210 } 211 212 err = session.SaveChanges() 213 if err != nil { 214 log.Fatalf("session.SaveChanges() failed with %s\n", err) 215 } 216 ``` 217 Second argument to `DeleteByID` is optional `changeVector`, for fine-grain concurrency control. 218 219 See `crudDeleteUsingID()` in [examples/main.go](examples/main.go) for full example. 220 221 ## Querying documents 222 223 ### Selecting what to query 224 225 First you need to decide what to query. 226 227 RavenDB stores documents in collections. By default each type (struct) is stored in its own collection e.g. all `Employee` structs are stored in `employees` collection. 228 229 You can query by collection name: 230 231 ```go 232 q := session.QueryCollection("employees") 233 ``` 234 235 See `queryCollectionByName()` in [examples/main.go](examples/main.go) for full example. 236 237 To get a collection name for a given type use `ravendb.GetCollectionNameDefault(&MyStruct{})`. 238 239 You can query a collection for a given type: 240 241 ```go 242 tp := reflect.TypeOf(&northwind.Employee{}) 243 q := session.QueryCollectionForType(tp) 244 ``` 245 See `queryCollectionByType()` in [examples/main.go](examples/main.go) for full example. 246 247 You can query an index: 248 249 ```go 250 q := session.QueryIndex("Orders/ByCompany") 251 ``` 252 See `queryIndex()` in [examples/main.go](examples/main.go) for full example. 253 254 ### Limit what is returned 255 256 ```go 257 tp := reflect.TypeOf(&northwind.Product{}) 258 q := session.QueryCollectionForType(tp) 259 260 q = q.WaitForNonStaleResults(0) 261 q = q.WhereEquals("Name", "iPhone X") 262 q = q.OrderBy("PricePerUnit") 263 q = q.Take(2) // limit to 2 results 264 ``` 265 See `queryComplex()` in [examples/main.go](examples/main.go) for full example. 266 267 ### Obtain the results 268 269 You can get all matching results: 270 271 ```go 272 var products []*northwind.Product 273 err = q.GetResults(&products) 274 ``` 275 See `queryComplex()` in [examples/main.go](examples/main.go) for full example. 276 277 You can get just first one: 278 ```go 279 var first *northwind.Employee 280 err = q.First(&first) 281 ``` 282 See `queryFirst()` in [examples/main.go](examples/main.go) for full example. 283 284 ## Overview of [DocumentQuery](https://godoc.org/github.com/altipla-consulting/ravendb-go-client#DocumentQuery) methods 285 286 ### SelectFields() - projections using a single field 287 288 ```go 289 // RQL equivalent: from employees select FirstName 290 q = q.SelectFields(reflect.TypeOf(""), "FirstName") 291 292 var names []string 293 err = q.GetResults(&names) 294 ``` 295 See `querySelectSingleField()` in [examples/main.go](examples/main.go) for full example. 296 297 ### SelectFields() - projections using multiple fields 298 299 ```go 300 type employeeNameTitle struct { 301 FirstName string 302 Title string 303 } 304 305 // RQL equivalent: from employees select FirstName, Title 306 tp := reflect.TypeOf(&northwind.Employee{}) 307 q := session.QueryCollectionForType(tp) 308 q = q.SelectFields(reflect.TypeOf(&employeeNameTitle{}), "FirstName", "Title") 309 ``` 310 See `querySelectFields()` in [examples/main.go](examples/main.go) for full example. 311 312 ### Distinct() 313 314 ```go 315 // RQL equivalent: from employees select distinct Title 316 tp := reflect.TypeOf(&northwind.Employee{}) 317 q := session.QueryCollectionForType(tp) 318 q = q.SelectFields(reflect.TypeOf(""), "Title") 319 q = q.Distinct() 320 ``` 321 See `queryDistinct()` in [examples/main.go](examples/main.go) for full example. 322 323 ### WhereEquals() / WhereNotEquals() 324 325 ```go 326 // RQL equivalent: from employees where Title = 'Sales Representative' 327 tp := reflect.TypeOf(&northwind.Employee{}) 328 q := session.QueryCollectionForType(tp) 329 q = q.WhereEquals("Title", "Sales Representative") 330 ``` 331 See `queryEquals()` in [examples/main.go](examples/main.go) for full example. 332 333 ### WhereIn 334 335 ```go 336 // RQL equivalent: from employees where Title in ['Sales Representative', 'Sales Manager'] 337 tp := reflect.TypeOf(&northwind.Employee{}) 338 q := session.QueryCollectionForType(tp) 339 q = q.WhereIn("Title", []interface{}{"Sales Representative", "Sales Manager"}) 340 ``` 341 See `queryIn()` in [examples/main.go](examples/main.go) for full example. 342 343 ### WhereStartsWith() / WhereEndsWith() 344 345 ```go 346 // RQL equivalent: 347 // from employees where startsWith('Ro') 348 tp := reflect.TypeOf(&northwind.Employee{}) 349 q := session.QueryCollectionForType(tp) 350 q = q.WhereStartsWith("FirstName", "Ro") 351 ``` 352 See `queryStartsWith()` and `queryEndsWith` in [examples/main.go](examples/main.go) for full example. 353 354 ### WhereBetween() 355 356 ```go 357 // RQL equivalent: 358 // from orders where Freight between 11 and 13 359 tp := reflect.TypeOf(&northwind.Order{}) 360 q := session.QueryCollectionForType(tp) 361 q = q.WhereBetween("Freight", 11, 13) 362 ``` 363 See `queryBetween()` in [examples/main.go](examples/main.go) for full example. 364 365 ### WhereGreaterThan() / WhereGreaterThanOrEqual() / WhereLessThan() / WhereLessThanOrEqual() 366 367 ```go 368 // RQL equivalent: 369 // from orders where Freight Freight > 11 370 tp := reflect.TypeOf(&northwind.Order{}) 371 q := session.QueryCollectionForType(tp) 372 // can also be WhereGreaterThanOrEqual(), WhereLessThan(), WhereLessThanOrEqual() 373 q = q.WhereGreaterThan("Freight", 11) 374 ``` 375 See `queryGreater()` in [examples/main.go](examples/main.go) for full example. 376 377 ### WhereExists() 378 379 Checks if the field exists. 380 381 ```go 382 // RQL equivalent: 383 // from employees where exists ("ReportsTo") 384 tp := reflect.TypeOf(&northwind.Employee{}) 385 q := session.QueryCollectionForType(tp) 386 q = q.WhereExists("ReportsTo") 387 ``` 388 See `queryExists()` in [examples/main.go](examples/main.go) for full example. 389 390 ### ContainsAny() / ContainsAll() 391 392 ```go 393 // RQL equivalent: 394 // from employees where FirstName in ("Anne", "Nancy") 395 tp := reflect.TypeOf(&northwind.Employee{}) 396 q := session.QueryCollectionForType(tp) 397 q = q.ContainsAny("FirstName", []interface{}{"Anne", "Nancy"}) 398 ``` 399 See `queryContainsAny()` in [examples/main.go](examples/main.go) for full example. 400 401 ### Search() 402 403 Performs full-text search: 404 405 ```go 406 // RQL equivalent: 407 // from employees where search(FirstName, 'Anne Nancy') 408 tp := reflect.TypeOf(&northwind.Employee{}) 409 q := session.QueryCollectionForType(tp) 410 q = q.Search("FirstName", "Anne Nancy") 411 ``` 412 See `querySearch()` in [examples/main.go](examples/main.go) for full example. 413 414 ### OpenSubclause() / CloseSubclause() 415 416 ```go 417 // RQL equivalent: 418 // from employees where (FirstName = 'Steven') or (Title = 'Sales Representative' and LastName = 'Davolio') 419 tp := reflect.TypeOf(&northwind.Employee{}) 420 q := session.QueryCollectionForType(tp) 421 q = q.WhereEquals("FirstName", "Steven") 422 q = q.OrElse() 423 q = q.OpenSubclause() 424 q = q.WhereEquals("Title", "Sales Representative") 425 q = q.WhereEquals("LastName", "Davolio") 426 q = q.CloseSubclause() 427 ``` 428 See `querySubclause()` in [examples/main.go](examples/main.go) for full example. 429 430 ### Not() 431 432 ```go 433 // RQL equivalent: 434 // from employees where not FirstName = 'Steven' 435 tp := reflect.TypeOf(&northwind.Employee{}) 436 q := session.QueryCollectionForType(tp) 437 q = q.Not() 438 q = q.WhereEquals("FirstName", "Steven") 439 ``` 440 See `queryNot()` in [examples/main.go](examples/main.go) for full example. 441 442 ### AndAlso() / OrElse() 443 444 ```go 445 // RQL equivalent: 446 // from employees where FirstName = 'Steven' or FirstName = 'Nancy' 447 tp := reflect.TypeOf(&northwind.Employee{}) 448 q := session.QueryCollectionForType(tp) 449 q = q.WhereEquals("FirstName", "Steven") 450 // can also be AndElse() 451 q = q.OrElse() 452 q = q.WhereEquals("FirstName", "Nancy") 453 ``` 454 See `queryOrElse()` in [examples/main.go](examples/main.go) for full example. 455 456 ### UsingDefaultOperator() 457 458 Sets default operator (which will be used if no `AndAlso()` / `OrElse()` was called. Just after query instantiation, OR is used as default operator. Default operator can be changed only adding any conditions. 459 460 ### OrderBy() / RandomOrdering() 461 462 ```go 463 // RQL equivalent: 464 // from employees order by FirstName 465 tp := reflect.TypeOf(&northwind.Employee{}) 466 q := session.QueryCollectionForType(tp) 467 // can also be RandomOrdering() 468 q = q.OrderBy("FirstName") 469 ``` 470 See `queryOrderBy()` in [examples/main.go](examples/main.go) for full example. 471 472 ### Take() 473 474 ```go 475 // RQL equivalent: 476 // from employees order by FirstName desc 477 tp := reflect.TypeOf(&northwind.Employee{}) 478 q := session.QueryCollectionForType(tp) 479 q = q.OrderByDescending("FirstName") 480 q = q.Take(2) 481 ``` 482 See `queryTake()` in [examples/main.go](examples/main.go) for full example. 483 484 ### Skip() 485 486 ```go 487 // RQL equivalent: 488 // from employees order by FirstName desc 489 tp := reflect.TypeOf(&northwind.Employee{}) 490 q := session.QueryCollectionForType(tp) 491 q = q.OrderByDescending("FirstName") 492 q = q.Take(2) 493 q = q.Skip(1) 494 ``` 495 See `querySkip()` in [examples/main.go](examples/main.go) for full example. 496 497 ### Getting query statistics 498 499 To obtain query statistics use `Statistics()` method. 500 501 ```go 502 var stats *ravendb.QueryStatistics 503 tp := reflect.TypeOf(&northwind.Employee{}) 504 q := session.QueryCollectionForType(tp) 505 q = q.WhereGreaterThan("FirstName", "Bernard") 506 q = q.OrderByDescending("FirstName") 507 q.Statistics(&stats) 508 ``` 509 Statistics: 510 ``` 511 Statistics: 512 {IsStale: false, 513 DurationInMs: 0, 514 TotalResults: 7, 515 SkippedResults: 0, 516 Timestamp: 2019-02-13 02:57:31.5226409 +0000 UTC, 517 IndexName: "Auto/employees/ByLastNameAndReportsToAndSearch(FirstName)AndTitle", 518 IndexTimestamp: 2019-02-13 02:57:31.5226409 +0000 UTC, 519 LastQueryTime: 2019-02-13 03:50:25.7602429 +0000 UTC, 520 TimingsInMs: {}, 521 ResultEtag: 7591488513381790088, 522 ResultSize: 0, 523 ScoreExplanations: {}} 524 ``` 525 See `queryStatistics()` in [examples/main.go](examples/main.go) for full example. 526 527 ### GetResults() / First() / Single() / Count() 528 529 `GetResults()` - returns all results 530 531 `First()` - first result 532 533 `Single()` - first result, returns error if there's more entries 534 535 `Count()` - returns the number of the results (not affected by take()) 536 537 See `queryFirst()`, `querySingle()` and `queryCount()` in [examples/main.go](examples/main.go) for full example. 538 539 ## Attachments 540 541 ### Store attachments 542 543 ```go 544 fileStream, err := os.Open(path) 545 if err != nil { 546 log.Fatalf("os.Open() failed with '%s'\n", err) 547 } 548 defer fileStream.Close() 549 550 fmt.Printf("new employee id: %s\n", e.ID) 551 err = session.Advanced().Attachments().Store(e, "photo.png", fileStream, "image/png") 552 553 // could also be done using document id 554 // err = session.Advanced().Attachments().Store(e.ID, "photo.png", fileStream, "image/png") 555 556 if err != nil { 557 log.Fatalf("session.Advanced().Attachments().Store() failed with '%s'\n", err) 558 } 559 560 err = session.SaveChanges() 561 ``` 562 See `storeAttachments()` in [examples/main.go](examples/main.go) for full example. 563 564 ### Get attachments 565 566 ```go 567 attachment, err := session.Advanced().Attachments().Get(docID, "photo.png") 568 if err != nil { 569 log.Fatalf("session.Advanced().Attachments().Get() failed with '%s'\n", err) 570 } 571 defer attachment.Close() 572 fmt.Print("Attachment details:\n") 573 pretty.Print(attachment.Details) 574 // read attachment data 575 // attachment.Data is io.Reader 576 var attachmentData bytes.Buffer 577 n, err := io.Copy(&attachmentData, attachment.Data) 578 if err != nil { 579 log.Fatalf("io.Copy() failed with '%s'\n", err) 580 } 581 fmt.Printf("Attachment size: %d bytes\n", n) 582 ``` 583 584 Attachment details: 585 ``` 586 {AttachmentName: {Name: "photo.png", 587 Hash: "MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=", 588 ContentType: "image/png", 589 Size: 4579}, 590 ChangeVector: "A:4905-dMAeI9ANZ06DOxCRLnSmNw", 591 DocumentID: "employees/44-A"} 592 Attachment size: 4579 bytes 593 ``` 594 595 See `getAttachments()` in [examples/main.go](examples/main.go) for full example. 596 597 ### Check if attachment exists 598 599 ```go 600 name := "photo.png" 601 exists, err := session.Advanced().Attachments().Exists(docID, name) 602 if err != nil { 603 log.Fatalf("session.Advanced().Attachments().Exists() failed with '%s'\n", err) 604 } 605 ``` 606 See `checkAttachmentExists()` in [examples/main.go](examples/main.go) for full example. 607 608 ### Get attachment names 609 610 ```go 611 names, err := session.Advanced().Attachments().GetNames(doc) 612 if err != nil { 613 log.Fatalf("session.Advanced().Attachments().GetNames() failed with '%s'\n", err) 614 } 615 ``` 616 617 Attachment names: 618 ``` 619 [{Name: "photo.png", 620 Hash: "MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=", 621 ContentType: "image/png", 622 Size: 4579}] 623 ``` 624 625 See `getAttachmentNames()` in [examples/main.go](examples/main.go) for full example. 626 627 628 ## Bulk insert 629 630 When storing multiple documents, use bulk insertion. 631 632 ```go 633 bulkInsert := store.BulkInsert("") 634 635 names := []string{"Anna", "Maria", "Miguel", "Emanuel", "Dayanara", "Aleida"} 636 for _, name := range names { 637 e := &northwind.Employee{ 638 FirstName: name, 639 } 640 id, err := bulkInsert.Store(e, nil) 641 if err != nil { 642 log.Fatalf("bulkInsert.Store() failed with '%s'\n", err) 643 } 644 } 645 // flush data and finish 646 err = bulkInsert.Close() 647 ``` 648 649 See `bulkInsert()` in [examples/main.go](examples/main.go) for full example. 650 651 ## Observing changes in the database 652 653 Listen for database changes e.g. document changes. 654 655 ```go 656 changes := store.Changes("") 657 658 err = changes.EnsureConnectedNow() 659 if err != nil { 660 log.Fatalf("changes.EnsureConnectedNow() failed with '%s'\n", err) 661 } 662 663 cb := func(change *ravendb.DocumentChange) { 664 fmt.Print("change:\n") 665 pretty.Print(change) 666 } 667 docChangesCancel, err := changes.ForAllDocuments(cb) 668 if err != nil { 669 log.Fatalf("changes.ForAllDocuments() failed with '%s'\n", err) 670 } 671 672 defer docChangesCancel() 673 674 e := &northwind.Employee{ 675 FirstName: "Jon", 676 LastName: "Snow", 677 } 678 err = session.Store(e) 679 if err != nil { 680 log.Fatalf("session.Store() failed with '%s'\n", err) 681 } 682 683 err = session.SaveChanges() 684 if err != nil { 685 log.Fatalf("session.SaveChanges() failed with '%s'\n", err) 686 } 687 // cb should now be called notifying there's a new document 688 ``` 689 690 Example change: 691 ``` 692 {Type: "Put", 693 ID: "Raven/Hilo/employees", 694 CollectionName: "@hilo", 695 ChangeVector: "A:4892-bJERJNLunE+4xQ/yDEuk1Q"} 696 ``` 697 698 See `changes()` in [examples/main.go](examples/main.go) for full example. 699 700 ## Streaming 701 702 Streaming allows interating over documents matching certain criteria. 703 704 It's useful when there's a large number of results as it limits memory 705 use by reading documents in batches (as opposed to all at once). 706 707 ### Stream documents with ID prefix 708 709 Here we iterate over all documents in `products` collection: 710 711 ```go 712 args := &ravendb.StartsWithArgs{ 713 StartsWith: "products/", 714 } 715 iterator, err := session.Advanced().Stream(args) 716 if err != nil { 717 log.Fatalf("session.Advanced().Stream() failed with '%s'\n", err) 718 } 719 for { 720 var p *northwind.Product 721 streamResult, err := iterator.Next(&p) 722 if err != nil { 723 // io.EOF means there are no more results 724 if err == io.EOF { 725 err = nil 726 } else { 727 log.Fatalf("iterator.Next() failed with '%s'\n", err) 728 } 729 break 730 } 731 // handle p 732 } 733 ``` 734 See `streamWithIDPrefix()` in [examples/main.go](examples/main.go) for full example. 735 736 This returns: 737 ``` 738 streamResult: 739 {ID: "products/1-A", 740 ChangeVector: "A:96-bJERJNLunE+4xQ/yDEuk1Q", 741 Metadata: {}, 742 Document: ... same as product but as map[string]interface{} ... 743 744 product: 745 {ID: "products/1-A", 746 Name: "Chai", 747 Supplier: "suppliers/1-A", 748 Category: "categories/1-A", 749 QuantityPerUnit: "10 boxes x 20 bags", 750 PricePerUnit: 18, 751 UnitsInStock: 1, 752 UnistsOnOrder: 0, 753 Discontinued: false, 754 ReorderLevel: 10} 755 ``` 756 757 ### Stream query results 758 759 ```go 760 tp := reflect.TypeOf(&northwind.Product{}) 761 q := session.QueryCollectionForType(tp) 762 q = q.WhereGreaterThan("PricePerUnit", 15) 763 q = q.OrderByDescending("PricePerUnit") 764 765 iterator, err := session.Advanced().StreamQuery(q, nil) 766 if err != nil { 767 log.Fatalf("session.Advanced().StreamQuery() failed with '%s'\n", err) 768 } 769 // rest of processing as above 770 ``` 771 772 See `streamQueryResults()` in [examples/main.go](examples/main.go) for full example. 773 774 ## Revisions 775 776 Note: make sure to enable revisions in a given store using `NewConfigureRevisionsOperation` operation. 777 778 ```go 779 e := &northwind.Employee{ 780 FirstName: "Jon", 781 LastName: "Snow", 782 } 783 err = session.Store(e) 784 if err != nil { 785 log.Fatalf("session.Store() failed with '%s'\n", err) 786 } 787 err = session.SaveChanges() 788 if err != nil { 789 log.Fatalf("session.SaveChanges() failed with '%s'\n", err) 790 } 791 792 // modify document to create a new revision 793 e.FirstName = "Jhonny" 794 err = session.SaveChanges() 795 if err != nil { 796 log.Fatalf("session.SaveChanges() failed with '%s'\n", err) 797 } 798 799 var revisions []*northwind.Employee 800 err = session.Advanced().Revisions().GetFor(&revisions, e.ID) 801 ``` 802 See `revisions()` in [examples/main.go](examples/main.go) for full example. 803 804 Returns: 805 ``` 806 [{ID: "employees/43-A", 807 LastName: "Snow", 808 FirstName: "Jhonny", 809 Title: "", 810 Address: nil, 811 HiredAt: {}, 812 Birthday: {}, 813 HomePhone: "", 814 Extension: "", 815 ReportsTo: "", 816 Notes: [], 817 Territories: []}, 818 {ID: "employees/43-A", 819 LastName: "Snow", 820 FirstName: "Jon", 821 Title: "", 822 Address: nil, 823 HiredAt: {}, 824 Birthday: {}, 825 HomePhone: "", 826 Extension: "", 827 ReportsTo: "", 828 Notes: [], 829 Territories: []}] 830 ``` 831 832 ## Suggestions 833 834 Suggestions provides similarity queries. Here we're asking for `FirstName` values similar to `Micael` and the database suggests `Michael`. 835 836 ```go 837 index := ravendb.NewIndexCreationTask("EmployeeIndex") 838 index.Map = "from doc in docs.Employees select new { doc.FirstName }" 839 index.Suggestion("FirstName") 840 841 err = store.ExecuteIndex(index, "") 842 if err != nil { 843 log.Fatalf("store.ExecuteIndex() failed with '%s'\n", err) 844 } 845 846 tp := reflect.TypeOf(&northwind.Employee{}) 847 q := session.QueryCollectionForType(tp) 848 su := ravendb.NewSuggestionWithTerm("FirstName") 849 su.Term = "Micael" 850 suggestionQuery := q.SuggestUsing(su) 851 results, err := suggestionQuery.Execute() 852 ``` 853 See `suggestions()` in [examples/main.go](examples/main.go) for full example. 854 855 Returns: 856 ``` 857 {FirstName: {Name: "FirstName", 858 Suggestions: ["michael"]}} 859 ``` 860 861 ## Advanced patching 862 863 To update documents more efficiently than sending the whole document, you can patch just a given field or atomically add/substract values 864 of numeric fields. 865 866 ```go 867 err = session.Advanced().IncrementByID(product.ID, "PricePerUnit", 15) 868 if err != nil { 869 log.Fatalf("session.Advanced().IncrementByID() failed with %s\n", err) 870 } 871 872 err = session.Advanced().Patch(product, "Category", "expensive products") 873 if err != nil { 874 log.Fatalf("session.Advanced().PatchEntity() failed with %s\n", err) 875 } 876 877 err = session.SaveChanges() 878 if err != nil { 879 log.Fatalf("session.SaveChanges() failed with %s\n", err) 880 } 881 ``` 882 See `advancedPatching()` in [examples/main.go](examples/main.go) for full example. 883 884 ## Subscriptions 885 886 ```go 887 opts := ravendb.SubscriptionCreationOptions{ 888 Query: "from Products where PricePerUnit > 17 and PricePerUnit < 19", 889 } 890 subscriptionName, err := store.Subscriptions().Create(&opts, "") 891 if err != nil { 892 log.Fatalf("store.Subscriptions().Create() failed with %s\n", err) 893 } 894 wopts := ravendb.NewSubscriptionWorkerOptions(subscriptionName) 895 worker, err := store.Subscriptions().GetSubscriptionWorker(tp, wopts, "") 896 if err != nil { 897 log.Fatalf("store.Subscriptions().GetSubscriptionWorker() failed with %s\n", err) 898 } 899 900 results := make(chan *ravendb.SubscriptionBatch, 16) 901 cb := func(batch *ravendb.SubscriptionBatch) error { 902 results <- batch 903 return nil 904 } 905 err = worker.Run(cb) 906 if err != nil { 907 log.Fatalf("worker.Run() failed with %s\n", err) 908 } 909 910 // wait for first batch result 911 select { 912 case batch := <-results: 913 fmt.Print("Batch of subscription results:\n") 914 pretty.Print(batch) 915 case <-time.After(time.Second * 5): 916 fmt.Printf("Timed out waiting for first subscription batch\n") 917 918 } 919 920 _ = worker.Close() 921 ``` 922 See `subscriptions()` in [examples/main.go](examples/main.go) for full example.