github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/dive-into-raven/main.go (about) 1 package main 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "fmt" 7 "io" 8 "mime" 9 "os" 10 "path/filepath" 11 "reflect" 12 "strings" 13 "time" 14 15 "github.com/kylelemons/godebug/pretty" 16 "github.com/ravendb/ravendb-go-client" 17 "github.com/ravendb/ravendb-go-client/examples/northwind" 18 ) 19 20 var ( 21 // change to false to run the examples against a 22 // local server running on port 8080 23 usePublicTestServer = false 24 25 // if running RavenDB locally on port 8080 26 serverLocalURL = "http://localhost:8080" 27 28 // if using public RavenDB test instance 29 serverPublicTestURL = "http://live-test.ravendb.net" 30 31 testDatabaseName string 32 ) 33 34 // for optional logging 35 var ( 36 // if true, we'll show summary of HTTP requests made to the server 37 // and dump full info about failed HTTP requests 38 verboseLogging = false 39 40 // if true, logs all http requests/responses to a file for further inspection 41 // this is for use in tests so the file has a fixed location: 42 // logs/trace_${test_name}_go.txt 43 logAllRequests = true 44 45 // if logAllRequests is true, this is a path of a file where we log 46 // info about all HTTP requests 47 logAllRequestsPath = "http_requests_log.txt" 48 ) 49 50 var ( 51 serverURL = "http://localhost:8080" 52 databaseName = "YourDatabaseName" 53 ) 54 55 var ( 56 globalDocumentStore *ravendb.DocumentStore 57 ) 58 59 func createDocumentStore() (*ravendb.DocumentStore, error) { 60 if globalDocumentStore != nil { 61 return globalDocumentStore, nil 62 } 63 urls := []string{serverURL} 64 store := ravendb.NewDocumentStore(urls, databaseName) 65 err := store.Initialize() 66 if err != nil { 67 return nil, err 68 } 69 globalDocumentStore = store 70 return globalDocumentStore, nil 71 } 72 73 func genUID() string { 74 var u [16]byte 75 _, _ = io.ReadFull(rand.Reader, u[:]) 76 return hex.EncodeToString(u[:]) 77 } 78 79 func genRandomDatabaseName() string { 80 return "demo-" + genUID() 81 } 82 83 func waitForIndexing(store *ravendb.DocumentStore, database string, timeout time.Duration) error { 84 admin := store.Maintenance().ForDatabase(database) 85 if timeout == 0 { 86 timeout = time.Minute 87 } 88 89 sp := time.Now() 90 for time.Since(sp) < timeout { 91 op := ravendb.NewGetStatisticsOperation("") 92 err := admin.Send(op) 93 if err != nil { 94 return err 95 } 96 databaseStatistics := op.Command.Result 97 isDone := true 98 hasError := false 99 for _, index := range databaseStatistics.Indexes { 100 if index.State == ravendb.IndexStateDisabled { 101 continue 102 } 103 if index.IsStale || strings.HasPrefix(index.Name, ravendb.IndexingSideBySideIndexNamePrefix) { 104 isDone = false 105 } 106 if index.State == ravendb.IndexStateError { 107 hasError = true 108 } 109 } 110 if isDone { 111 return nil 112 } 113 if hasError { 114 break 115 } 116 time.Sleep(time.Millisecond * 100) 117 } 118 119 op := ravendb.NewGetIndexErrorsOperation(nil) 120 err := admin.Send(op) 121 if err != nil { 122 return err 123 } 124 return ravendb.NewTimeoutError("The indexes stayed stale for more than %s", timeout) 125 } 126 127 func createSampleNorthwindDatabase(store *ravendb.DocumentStore) error { 128 sampleData := ravendb.NewCreateSampleDataOperation() 129 err := store.Maintenance().Send(sampleData) 130 if err != nil { 131 fmt.Printf("createSampleNorthwindDatabase: store.Maintance().Send() failed with '%s'\n", err) 132 return err 133 } 134 err = waitForIndexing(store, store.GetDatabase(), 0) 135 if err != nil { 136 fmt.Printf("watiForIndexing() failed with '%s'\n", err) 137 return err 138 } 139 return nil 140 } 141 142 // create a new, randomly named database for just tests and populate with 143 // sample Northwind data. 144 // if usePublicTestServer we'll use public RavenDB instance. Otherwise 145 // we'll talk to local server on port 8080 146 func createTestDocumentStore() (*ravendb.DocumentStore, error) { 147 if globalDocumentStore != nil { 148 return globalDocumentStore, nil 149 } 150 urls := []string{serverLocalURL} 151 if usePublicTestServer { 152 urls[0] = serverPublicTestURL 153 } 154 155 testDatabaseName = genRandomDatabaseName() 156 databaseName = testDatabaseName 157 158 // "test.manager" is a dummy database 159 // we need a store, even if it points to a dummy database, 160 // to create a new database and then create a store out of thtat 161 storeManager := ravendb.NewDocumentStore(urls, "test.manager") 162 163 err := storeManager.Initialize() 164 if err != nil { 165 fmt.Printf("createTestDocumentStore: storeManager.Initialize() failed with '%s'\n", err) 166 return nil, err 167 } 168 169 databaseRecord := ravendb.NewDatabaseRecord() 170 databaseRecord.DatabaseName = testDatabaseName 171 172 // replicationFactor seems to be a minimum number of nodes with the data 173 // so it must be less than 3 (we have 3 nodes and might kill one, leaving 174 // only 2) 175 createDatabaseOperation := ravendb.NewCreateDatabaseOperation(databaseRecord, 1) 176 err = storeManager.Maintenance().Server().Send(createDatabaseOperation) 177 if err != nil { 178 fmt.Printf("d.store.Maintenance().Server().Send(createDatabaseOperation) failed with %s\n", err) 179 return nil, err 180 } 181 182 store := ravendb.NewDocumentStore(urls, testDatabaseName) 183 err = store.Initialize() 184 if err != nil { 185 fmt.Printf("createTestDocumentStore: store.Initialize() failed with '%s'\n", err) 186 return nil, err 187 } 188 189 fmt.Printf("Created a test database '%s'\n", testDatabaseName) 190 globalDocumentStore = store 191 err = createSampleNorthwindDatabase(store) 192 if err != nil { 193 fmt.Printf("createTestDocumentStore: createSampleNorthwindDatabase() failed with '%s'\n", err) 194 return nil, err 195 } 196 197 return globalDocumentStore, nil 198 } 199 200 func deleteTestDatabase() error { 201 if globalDocumentStore == nil || testDatabaseName == "" { 202 return nil 203 } 204 fmt.Printf("Deleting test database '%s'\n", testDatabaseName) 205 op := ravendb.NewDeleteDatabasesOperation(testDatabaseName, true) 206 return globalDocumentStore.Maintenance().Server().Send(op) 207 } 208 209 func createDocument(companyName, companyPhone, contactName, contactTitle string) error { 210 newCompany := &northwind.Company{ 211 Name: companyName, 212 Phone: companyPhone, 213 Contact: &northwind.Contact{ 214 Name: contactName, 215 Title: contactTitle, 216 }, 217 } 218 219 session, err := globalDocumentStore.OpenSession("") 220 if err != nil { 221 return err 222 } 223 defer session.Close() 224 225 err = session.Store(newCompany) 226 if err != nil { 227 return err 228 } 229 230 theNewDocumentID := newCompany.ID 231 232 err = session.SaveChanges() 233 if err != nil { 234 return err 235 } 236 237 fmt.Printf("Created a new document with id: %s\n", theNewDocumentID) 238 return nil 239 } 240 241 func session() error { 242 session, err := globalDocumentStore.OpenSession("") 243 if err != nil { 244 return err 245 } 246 // Run your business logic: 247 // 248 // Store documents 249 // Load and Modify documents 250 // Query indexes & collections 251 // Delete documents 252 // .... etc. 253 254 err = session.SaveChanges() 255 if err != nil { 256 return err 257 } 258 259 // make sure to close the session 260 session.Close() 261 262 return nil 263 } 264 265 func editDocument(companyName string) error { 266 session, err := globalDocumentStore.OpenSession("") 267 if err != nil { 268 return err 269 } 270 defer session.Close() 271 272 var company *northwind.Company 273 err = session.Load(&company, "companies/5-A") 274 if err != nil { 275 return err 276 } 277 // if not found, company is not changed and will remain nil 278 if company == nil { 279 return nil 280 } 281 company.Name = companyName 282 283 err = session.SaveChanges() 284 if err != nil { 285 return err 286 } 287 288 return nil 289 } 290 291 func deleteDocument(documentID string) error { 292 session, err := globalDocumentStore.OpenSession("") 293 if err != nil { 294 return err 295 } 296 defer session.Close() 297 298 err = session.DeleteByID(documentID, "") 299 if err != nil { 300 return err 301 } 302 303 err = session.SaveChanges() 304 if err != nil { 305 return err 306 } 307 308 return nil 309 } 310 311 func createRelatedDocuments(productName, supplierName, supplierPhone string) error { 312 supplier := &northwind.Supplier{ 313 Name: supplierName, 314 Phone: supplierPhone, 315 } 316 317 category := &northwind.Category{ 318 Name: "NoSQL Databases", 319 Description: "Non-relational databases", 320 } 321 322 product := &northwind.Product{ 323 Name: productName, 324 } 325 326 session, err := globalDocumentStore.OpenSession("") 327 if err != nil { 328 return err 329 } 330 defer session.Close() 331 332 err = session.Store(supplier) 333 if err != nil { 334 return err 335 } 336 err = session.Store(category) 337 if err != nil { 338 return err 339 } 340 341 product.Supplier = supplier.ID 342 product.Category = category.ID 343 344 err = session.Store(product) 345 if err != nil { 346 return err 347 } 348 349 err = session.SaveChanges() 350 if err != nil { 351 return err 352 } 353 354 return nil 355 } 356 357 func loadRelatedDocuments(pricePerUnit float64, phone string) error { 358 session, err := globalDocumentStore.OpenSession("") 359 if err != nil { 360 return err 361 } 362 defer session.Close() 363 364 var product *northwind.Product 365 err = session.Include("supplier").Load(&product, "products/34-A") 366 if err != nil { 367 return err 368 } 369 if product == nil { 370 // not found 371 return nil 372 } 373 374 var supplier *northwind.Supplier 375 err = session.Load(&supplier, product.Supplier) 376 if err != nil || supplier == nil { 377 return err 378 } 379 380 product.PricePerUnit = pricePerUnit 381 supplier.Phone = phone 382 383 err = session.SaveChanges() 384 if err != nil { 385 return err 386 } 387 388 return nil 389 } 390 391 func queryRelatedDocuments() error { 392 session, err := globalDocumentStore.OpenSession("") 393 if err != nil { 394 return err 395 } 396 defer session.Close() 397 398 session.Advanced().SetMaxNumberOfRequestsPerSession(128) 399 400 queriedType := reflect.TypeOf(&northwind.Order{}) 401 q := session.QueryCollectionForType(queriedType) 402 q = q.Include("Lines.Product") 403 q = q.WhereNotEquals("ShippedAt", nil) 404 var shippedOrders []*northwind.Order 405 err = q.GetResults(&shippedOrders) 406 if err != nil { 407 return err 408 } 409 410 fmt.Printf("got %d shipped orders\n", len(shippedOrders)) 411 412 for _, shippedOrder := range shippedOrders { 413 var productIDs []string 414 for _, line := range shippedOrder.Lines { 415 productIDs = append(productIDs, line.Product) 416 } 417 418 for i, productID := range productIDs { 419 var product *northwind.Product 420 err = session.Load(&product, productID) 421 if err != nil { 422 return err 423 } 424 product.UnitsOnOrder += shippedOrder.Lines[i].Quantity 425 } 426 } 427 428 err = session.SaveChanges() 429 if err != nil { 430 return err 431 } 432 433 return nil 434 } 435 436 func indexRelatedDocuments(categoryName string) error { 437 index := ravendb.NewIndexCreationTask("Products/ByCategoryName") 438 index.Map = `docs.Products.Select(product => new { 439 CategoryName = (this.LoadDocument(product.Category, "Categories")).Name 440 }) 441 ` 442 err := globalDocumentStore.ExecuteIndex(index, "") 443 if err != nil { 444 return err 445 } 446 err = waitForIndexing(globalDocumentStore, "", 0) 447 if err != nil { 448 return err 449 } 450 451 session, err := globalDocumentStore.OpenSession("") 452 if err != nil { 453 return err 454 } 455 defer session.Close() 456 457 var productsWithCategoryName []*northwind.Product 458 q := session.QueryIndex(index.IndexName) 459 q = q.WhereEquals("CategoryName", categoryName) 460 err = q.GetResults(&productsWithCategoryName) 461 if err != nil { 462 return err 463 } 464 pretty.Print(productsWithCategoryName) 465 return nil 466 } 467 468 func storeAttachment(documentID string, attachmentPath string) error { 469 stream, err := os.Open(attachmentPath) 470 if err != nil { 471 return err 472 } 473 defer func() { 474 _ = stream.Close() 475 }() 476 477 contentType := mime.TypeByExtension(filepath.Ext(attachmentPath)) 478 attachmentName := filepath.Base(attachmentPath) 479 480 session, err := globalDocumentStore.OpenSession("") 481 if err != nil { 482 return err 483 } 484 defer session.Close() 485 486 err = session.Advanced().Attachments().StoreByID(documentID, attachmentName, stream, contentType) 487 if err != nil { 488 return err 489 } 490 491 err = session.SaveChanges() 492 if err != nil { 493 return err 494 } 495 496 return nil 497 } 498 499 func enableRevisions(collection1, collection2 string) error { 500 dur := ravendb.Duration(time.Hour * 24 * 14) 501 defaultConfig := &ravendb.RevisionsCollectionConfiguration{ 502 Disabled: false, 503 PurgeOnDelete: false, 504 MinimumRevisionsToKeep: 5, 505 MinimumRevisionAgeToKeep: &dur, 506 } 507 revisiionConfiguration1 := &ravendb.RevisionsCollectionConfiguration{ 508 Disabled: true, 509 } 510 revisiionConfiguration2 := &ravendb.RevisionsCollectionConfiguration{ 511 PurgeOnDelete: true, 512 } 513 collections := map[string]*ravendb.RevisionsCollectionConfiguration{ 514 collection1: revisiionConfiguration1, 515 collection2: revisiionConfiguration2, 516 } 517 518 myRevisionsConfiguration := &ravendb.RevisionsConfiguration{ 519 DefaultConfig: defaultConfig, 520 Collections: collections, 521 } 522 523 revisionsConfigurationOperation := ravendb.NewConfigureRevisionsOperation(myRevisionsConfiguration) 524 return globalDocumentStore.Maintenance().Send(revisionsConfigurationOperation) 525 } 526 527 func getRevisions() error { 528 myRevisionsConfiguration := &ravendb.RevisionsConfiguration{ 529 DefaultConfig: &ravendb.RevisionsCollectionConfiguration{ 530 Disabled: false, 531 }, 532 } 533 534 revisionsConfigurationOperation := ravendb.NewConfigureRevisionsOperation(myRevisionsConfiguration) 535 err := globalDocumentStore.Maintenance().Send(revisionsConfigurationOperation) 536 if err != nil { 537 return nil 538 } 539 540 session, err := globalDocumentStore.OpenSession("") 541 if err != nil { 542 return err 543 } 544 defer session.Close() 545 546 var company *northwind.Company 547 err = session.Load(&company, "companies/7-A") 548 if err != nil { 549 return err 550 } 551 company.Name = "Name 1" 552 err = session.SaveChanges() 553 if err != nil { 554 return err 555 } 556 557 company.Name = "Name 2" 558 company.Phone = "052-1234-567" 559 err = session.SaveChanges() 560 if err != nil { 561 return err 562 } 563 564 var revisions []*northwind.Company 565 err = session.Advanced().Revisions().GetFor(&revisions, "companies/7-A") 566 if err != nil { 567 return err 568 } 569 pretty.Print(revisions) 570 571 return nil 572 } 573 574 func queryOverview() error { 575 session, err := globalDocumentStore.OpenSession("") 576 if err != nil { 577 return err 578 } 579 defer session.Close() 580 581 queriedType := reflect.TypeOf(&northwind.Employee{}) 582 queryDefinition := session.QueryCollectionForType(queriedType) 583 584 // Define actions such as: 585 // Filter documents by documents fields 586 // Filter documents by text criteria 587 // Include related documents 588 // Get the query stats 589 // Sort results 590 // Customise the returned entity fields (Projections) 591 // Control results paging 592 593 var queryResults []*northwind.Employee 594 err = queryDefinition.GetResults(&queryResults) 595 if err != nil { 596 return err 597 } 598 fmt.Printf("Got %d results\n", len(queryResults)) 599 return nil 600 } 601 602 // EmployeeDetails describes details of an employee 603 type EmployeeDetails struct { 604 FullName string `json:"FullName"` 605 FirstName string `json:"FirstName"` 606 Title string `json:"Title"` 607 HiredAt ravendb.Time `json:"HiredAt"` 608 } 609 610 func queryExample() error { 611 session, err := globalDocumentStore.OpenSession("") 612 if err != nil { 613 return err 614 } 615 defer session.Close() 616 617 var queryResults []*EmployeeDetails 618 619 queriedType := reflect.TypeOf(&northwind.Employee{}) 620 query := session.QueryCollectionForType(queriedType) 621 { 622 query = query.OpenSubclause() 623 query = query.WhereEquals("FirstName", "Steven") 624 query = query.OrElse() 625 query = query.WhereEquals("Title", "Sales Representative") 626 query = query.CloseSubclause() 627 } 628 query = query.Include("ReportsTo") 629 630 var statistics *ravendb.QueryStatistics 631 query = query.Statistics(&statistics) 632 633 query = query.OrderByDescending("HiredAt") 634 635 projectedType := reflect.TypeOf(&EmployeeDetails{}) 636 fields := []string{ 637 "FirstName", 638 "Title", 639 "HiredAt", 640 } 641 query = query.SelectFields(projectedType, fields...) 642 query = query.Take(5) 643 err = query.GetResults(&queryResults) 644 if err != nil { 645 return err 646 } 647 fmt.Printf("Got %d results\n", len(queryResults)) 648 if len(queryResults) > 0 { 649 pretty.Print(queryResults[0]) 650 } 651 return nil 652 } 653 654 func fullCollectionQuery() error { 655 session, err := globalDocumentStore.OpenSession("") 656 if err != nil { 657 return err 658 } 659 defer session.Close() 660 661 queriedType := reflect.TypeOf(&northwind.Company{}) 662 fullCollectionQuery := session.QueryCollectionForType(queriedType) 663 664 var queryResults []*northwind.Company 665 err = fullCollectionQuery.GetResults(&queryResults) 666 if err != nil { 667 return err 668 } 669 fmt.Printf("Got %d results\n", len(queryResults)) 670 671 return nil 672 } 673 674 func queryByDocumentID(employeeDocumentID string) error { 675 session, err := globalDocumentStore.OpenSession("") 676 if err != nil { 677 return err 678 } 679 defer session.Close() 680 681 queriedType := reflect.TypeOf(&northwind.Employee{}) 682 queryByDocumentID := session.QueryCollectionForType(queriedType) 683 queryByDocumentID = queryByDocumentID.Where("ID", "==", employeeDocumentID) 684 685 var employee *northwind.Employee 686 err = queryByDocumentID.Single(&employee) 687 if err != nil { 688 return err 689 } 690 pretty.Print(employee) 691 692 return nil 693 } 694 695 func queryFilterResultsBasic() error { 696 session, err := globalDocumentStore.OpenSession("") 697 if err != nil { 698 return err 699 } 700 defer session.Close() 701 702 queriedType := reflect.TypeOf(&northwind.Employee{}) 703 filteredQuery := session.QueryCollectionForType(queriedType) 704 filteredQuery = filteredQuery.Where("FirstName", "==", "Anne") 705 706 var filteredEmployees []*northwind.Employee 707 err = filteredQuery.GetResults(&filteredEmployees) 708 if err != nil { 709 return err 710 } 711 fmt.Printf("Got %d results\n", len(filteredEmployees)) 712 if len(filteredEmployees) > 0 { 713 pretty.Print(filteredEmployees[0]) 714 715 } 716 717 return nil 718 } 719 720 func queryFilterResultsMultipleConditions(country string) error { 721 session, err := globalDocumentStore.OpenSession("") 722 if err != nil { 723 return err 724 } 725 defer session.Close() 726 727 queriedType := reflect.TypeOf(&northwind.Employee{}) 728 filteredQuery := session.QueryCollectionForType(queriedType) 729 filteredQuery = filteredQuery.WhereIn("FirstName", []interface{}{"Anne", "John"}) 730 filteredQuery = filteredQuery.OrElse() 731 { 732 filteredQuery = filteredQuery.OpenSubclause() 733 filteredQuery = filteredQuery.WhereEquals("Address.Country", country) 734 filteredQuery = filteredQuery.Where("Territories.Count", ">", 2) 735 filteredQuery = filteredQuery.WhereStartsWith("Title", "Sales") 736 filteredQuery = filteredQuery.CloseSubclause() 737 } 738 739 var filteredEmployees []*northwind.Employee 740 err = filteredQuery.GetResults(&filteredEmployees) 741 if err != nil { 742 return err 743 } 744 fmt.Printf("Got %d results\n", len(filteredEmployees)) 745 if len(filteredEmployees) > 0 { 746 pretty.Print(filteredEmployees[0]) 747 } 748 749 return nil 750 } 751 752 // CompanyDetails describes details about a company 753 type CompanyDetails struct { 754 CompanyName string `json:"CompanyName"` 755 City string `json:"City"` 756 Country string `json:"Country"` 757 } 758 759 func queryProjectingIndividualFields() error { 760 session, err := globalDocumentStore.OpenSession("") 761 if err != nil { 762 return err 763 } 764 defer session.Close() 765 766 queriedType := reflect.TypeOf(&northwind.Company{}) 767 projectedQuery := session.QueryCollectionForType(queriedType) 768 projectedType := reflect.TypeOf(&CompanyDetails{}) 769 fields := []string{"Name", "Address.City", "Address.Country"} 770 projections := []string{"CompanyName", "City", "Country"} 771 queryData := &ravendb.QueryData{ 772 Fields: fields, 773 Projections: projections, 774 } 775 projectedQuery = projectedQuery.SelectFieldsWithQueryData(projectedType, queryData) 776 var projectedResults []*CompanyDetails 777 err = projectedQuery.GetResults(&projectedResults) 778 if err != nil { 779 return err 780 } 781 fmt.Printf("Got %d results\n", len(projectedResults)) 782 if len(projectedResults) > 0 { 783 pretty.Print(projectedResults[0]) 784 } 785 return nil 786 } 787 788 func queryProjectingUsingFunctions() error { 789 session, err := globalDocumentStore.OpenSession("") 790 if err != nil { 791 return err 792 } 793 defer session.Close() 794 795 rawQuery := `declare function output(e) { 796 var format = function(p){ return p.FirstName + " " + p.LastName; }; 797 return { FullName : format(e), Title: e.Title, HiredAt: e.HiredAt }; 798 } 799 from Employees as e select output(e) 800 ` 801 query := session.Advanced().RawQuery(rawQuery) 802 var projectedResults []*EmployeeDetails 803 err = query.GetResults(&projectedResults) 804 if err != nil { 805 return err 806 } 807 fmt.Printf("Got %d results\n", len(projectedResults)) 808 if len(projectedResults) > 0 { 809 pretty.Print(projectedResults[0]) 810 } 811 return nil 812 } 813 814 func staticIndexesOverview() error { 815 indexName := "Employees/ByLastName" 816 index := ravendb.NewIndexCreationTask(indexName) 817 // Define: 818 // Map(s) functions 819 // Reduce function 820 // Additional indexing options per field 821 index.Map = "from e in docs.Employees select new { e.LastName }" 822 823 err := index.Execute(globalDocumentStore, nil, "") 824 if err != nil { 825 return err 826 } 827 828 session, err := globalDocumentStore.OpenSession("") 829 if err != nil { 830 return err 831 } 832 defer session.Close() 833 834 queryOnIndex := session.QueryIndex(indexName) 835 queryOnIndex = queryOnIndex.Where("LastName", "==", "SomeName") 836 var queryResults []*northwind.Employee 837 err = queryOnIndex.GetResults(&queryResults) 838 if err != nil { 839 return err 840 } 841 fmt.Printf("Got %d results\n", len(queryResults)) 842 if len(queryResults) > 0 { 843 pretty.Print(queryResults[0]) 844 } 845 return nil 846 } 847 848 func mapIndex(startYear int) error { 849 mapIndexDef := ` 850 docs.Employees.Select(e => new { 851 FullName = e.FirstName + " " + e.LastName, 852 Country = e.Address.Country, 853 WorkingInCompanySince = e.HiredAt.Year, 854 NumberOfTerritories = e.Territories.Count 855 } 856 ` 857 indexName := "Employees/ImportantDetails" 858 index := ravendb.NewIndexCreationTask(indexName) 859 index.Map = mapIndexDef 860 861 err := index.Execute(globalDocumentStore, nil, "") 862 if err != nil { 863 return err 864 } 865 err = waitForIndexing(globalDocumentStore, "", 0) 866 if err != nil { 867 return err 868 } 869 870 session, err := globalDocumentStore.OpenSession("") 871 if err != nil { 872 return err 873 } 874 defer session.Close() 875 876 query := session.QueryIndex(indexName) 877 query = query.Where("Country", "==", "USA") 878 query = query.Where("WorkingInCompanySince", ">", startYear) 879 880 var employeesFromUSA []*northwind.Employee 881 err = query.GetResults(&employeesFromUSA) 882 if err != nil { 883 return err 884 } 885 fmt.Printf("Got %d results\n", len(employeesFromUSA)) 886 if len(employeesFromUSA) > 0 { 887 pretty.Print(employeesFromUSA[0]) 888 } 889 return nil 890 } 891 892 func mapReduceIndex(country string) error { 893 indexName := "Employees/ByCountry" 894 index := ravendb.NewIndexCreationTask(indexName) 895 mapIndexDef := ` 896 map('employees', function(e) { 897 return { 898 Country: e.Address.Country, 899 CountryCount: 1 900 } 901 }) 902 ` 903 index.Map = mapIndexDef 904 905 reduceIndexDef := ` 906 groupBy(x => x.Country) 907 .aggregate(g => { 908 return { 909 Country: g.key, 910 Count: g.values.reduce((count, val) => val.CountryCount + count, 0) 911 } 912 }) 913 ` 914 index.Reduce = reduceIndexDef 915 916 err := index.Execute(globalDocumentStore, nil, "") 917 if err != nil { 918 return err 919 } 920 err = waitForIndexing(globalDocumentStore, "", 0) 921 if err != nil { 922 return err 923 } 924 925 session, err := globalDocumentStore.OpenSession("") 926 if err != nil { 927 return err 928 } 929 defer session.Close() 930 931 query := session.QueryIndex(indexName) 932 query = query.Where("Country", "==", country) 933 934 var queryResult *struct { 935 Country string 936 Count int 937 } 938 939 err = query.First(&queryResult) 940 if err != nil { 941 return err 942 } 943 if queryResult != nil { 944 fmt.Printf("Number of employees from country '%s': %d\n", queryResult.Country, queryResult.Count) 945 } 946 return nil 947 } 948 949 func autoMapIndex(firstName string) error { 950 session, err := globalDocumentStore.OpenSession("") 951 if err != nil { 952 return err 953 } 954 defer session.Close() 955 956 queriedType := reflect.TypeOf(&northwind.Employee{}) 957 query := session.QueryCollectionForType(queriedType) 958 query = query.Where("FirstName", "==", firstName) 959 960 var employeeResult *northwind.Employee 961 err = query.First(&employeeResult) 962 if err != nil { 963 return err 964 } 965 if employeeResult != nil { 966 pretty.Print(employeeResult) 967 } else { 968 fmt.Printf("No employee with first name '%s'\n", firstName) 969 } 970 return nil 971 } 972 973 func autoMapIndexTest() { 974 err := autoMapIndex("Steven") 975 if err != nil { 976 fmt.Printf("autoMapIndex() failed with '%s'\n", err) 977 } 978 } 979 980 func autoMapIndex2(country string) error { 981 session, err := globalDocumentStore.OpenSession("") 982 if err != nil { 983 return err 984 } 985 defer session.Close() 986 987 queriedType := reflect.TypeOf(&northwind.Employee{}) 988 query := session.QueryCollectionForType(queriedType) 989 query = query.WhereStartsWith("Title", "Sales") 990 query = query.Where("Address.Country", "==", country) 991 992 var employeeResult *northwind.Employee 993 err = query.First(&employeeResult) 994 if err != nil { 995 return err 996 } 997 if employeeResult != nil { 998 pretty.Print(employeeResult) 999 } else { 1000 fmt.Printf("No employee matching query\n") 1001 } 1002 return nil 1003 } 1004 1005 func fullTextSearchSingleField(searchTerm string) error { 1006 indexName := "Categories/DescriptionText" 1007 index := ravendb.NewIndexCreationTask(indexName) 1008 1009 index.Map = ` 1010 from c in docs.Categories 1011 select new { 1012 CategoryDescription = c.Description 1013 } 1014 ` 1015 index.Index("CategoryDescription", ravendb.FieldIndexingSearch) 1016 1017 err := index.Execute(globalDocumentStore, nil, "") 1018 if err != nil { 1019 return err 1020 } 1021 err = waitForIndexing(globalDocumentStore, "", 0) 1022 if err != nil { 1023 return err 1024 } 1025 1026 session, err := globalDocumentStore.OpenSession("") 1027 if err != nil { 1028 return err 1029 } 1030 defer session.Close() 1031 1032 query := session.QueryIndex(indexName) 1033 query = query.Where("CategoryDescription", "==", searchTerm) 1034 1035 var categoriesWithSearchTerm []*northwind.Category 1036 err = query.GetResults(&categoriesWithSearchTerm) 1037 if err != nil { 1038 return err 1039 } 1040 fmt.Printf("Get %d results\n", len(categoriesWithSearchTerm)) 1041 if len(categoriesWithSearchTerm) > 0 { 1042 pretty.Print(categoriesWithSearchTerm[0]) 1043 } 1044 1045 return nil 1046 } 1047 1048 // LastFm represents an last fm document 1049 type LastFm struct { 1050 ID string 1051 Artist string `json:"Artist"` 1052 Title string `json:"Title"` 1053 TrackID string `json:"TrackId"` 1054 Tags []string `json:"Tags"` 1055 TimeStamp ravendb.Time `json:"TimeStamp"` 1056 } 1057 1058 // TODO: this requires database that I don't know how to create 1059 func fullTextSearchMultipleField(searchTerm string) error { 1060 indexName := "Song/TextData" 1061 index := ravendb.NewIndexCreationTask(indexName) 1062 1063 index.Map = ` 1064 from song in docs.Songs 1065 select new { 1066 SongData = new { 1067 song.Artist, 1068 song.Title, 1069 song.Tags, 1070 song.TrackId 1071 } 1072 } 1073 ` 1074 index.Index("SongData", ravendb.FieldIndexingSearch) 1075 1076 err := index.Execute(globalDocumentStore, nil, "") 1077 if err != nil { 1078 return err 1079 } 1080 err = waitForIndexing(globalDocumentStore, "", 0) 1081 if err != nil { 1082 return err 1083 } 1084 1085 session, err := globalDocumentStore.OpenSession("") 1086 if err != nil { 1087 return err 1088 } 1089 defer session.Close() 1090 1091 query := session.QueryIndex(indexName) 1092 query = query.Search("SongData", searchTerm) 1093 query = query.Take(20) 1094 1095 var results []*LastFm 1096 err = query.GetResults(&results) 1097 if err != nil { 1098 return err 1099 } 1100 fmt.Printf("Get %d results\n", len(results)) 1101 if len(results) > 0 { 1102 pretty.Print(results[0]) 1103 } 1104 1105 return nil 1106 } 1107 1108 func createDatabase() error { 1109 databaseRecord := ravendb.NewDatabaseRecord() 1110 databaseRecord.DatabaseName = "NameOfDatabase" 1111 1112 createDatabaseOperation := ravendb.NewCreateDatabaseOperation(databaseRecord, 1) 1113 err := globalDocumentStore.Maintenance().Server().Send(createDatabaseOperation) 1114 if err != nil { 1115 if _, ok := err.(*ravendb.ConcurrencyError); ok { 1116 fmt.Printf("Database '%s' already exists\n", databaseRecord.DatabaseName) 1117 return nil 1118 } 1119 fmt.Printf("globalDocumentStore.Maintenance().Server().Send(createDatabaseOperation) failed with %s\n", err) 1120 return err 1121 } 1122 1123 return nil 1124 } 1125 1126 func createDatabaseTest() { 1127 err := createDatabase() 1128 if err != nil { 1129 fmt.Printf("createDatabase() failed with '%s'\n", err) 1130 } 1131 } 1132 1133 func fullTextSearchMultipleFieldTest() { 1134 err := fullTextSearchMultipleField("Floyd") 1135 if err != nil { 1136 fmt.Printf("fullTextSearchMultipleField() failed with '%s'\n", err) 1137 } 1138 } 1139 1140 func fullTextSearchSingleFieldTest() { 1141 err := fullTextSearchSingleField("pasta") 1142 if err != nil { 1143 fmt.Printf("fullTextSearchSingleField() failed with '%s'\n", err) 1144 } 1145 } 1146 1147 func autoMapIndex2Test() { 1148 err := autoMapIndex2("UK") 1149 if err != nil { 1150 fmt.Printf("autoMapIndex2() failed with '%s'\n", err) 1151 } 1152 } 1153 1154 func mapIndexTest() { 1155 err := mapIndex(1993) 1156 if err != nil { 1157 fmt.Printf("mapIndex() failed with '%s'\n", err) 1158 } 1159 } 1160 1161 func staticIndexesOverviewTest() { 1162 err := staticIndexesOverview() 1163 if err != nil { 1164 fmt.Printf("staticIndexesOverview() failed with '%s'\n", err) 1165 } 1166 } 1167 1168 func queryProjectingUsingFunctionsTest() { 1169 err := queryProjectingUsingFunctions() 1170 if err != nil { 1171 fmt.Printf("queryProjectingUsingFunctions() failed with '%s'\n", err) 1172 } 1173 } 1174 1175 func queryProjectingIndividualFieldsTest() { 1176 err := queryProjectingIndividualFields() 1177 if err != nil { 1178 fmt.Printf("queryProjectingIndividualFields() failed with '%s'\n", err) 1179 } 1180 } 1181 1182 func queryFilterResultsMultipleConditionsTest() { 1183 err := queryFilterResultsMultipleConditions("USA") 1184 if err != nil { 1185 fmt.Printf("queryFilterResultsMultipleConditions() failed with '%s'\n", err) 1186 } 1187 } 1188 1189 func queryFilterResultsBasicTest() { 1190 err := queryFilterResultsBasic() 1191 if err != nil { 1192 fmt.Printf("queryFilterResultsBasic() failed with '%s'\n", err) 1193 } 1194 } 1195 1196 func queryByDocumentIDTest() { 1197 err := queryByDocumentID("employees/1-A") 1198 if err != nil { 1199 fmt.Printf("queryByDocumentID() failed with '%s'\n", err) 1200 } 1201 } 1202 1203 func fullCollectionQueryTest() { 1204 err := fullCollectionQuery() 1205 if err != nil { 1206 fmt.Printf("fullCollectionQuery() failed with '%s'\n", err) 1207 } 1208 } 1209 1210 func queryExampleTest() { 1211 err := queryExample() 1212 if err != nil { 1213 fmt.Printf("queryExample() failed with '%s'\n", err) 1214 } 1215 } 1216 1217 func queryOverviewTest() { 1218 err := queryOverview() 1219 if err != nil { 1220 fmt.Printf("queryOverview() failed with '%s'\n", err) 1221 } 1222 } 1223 1224 func getRevisionsTest() { 1225 err := getRevisions() 1226 if err != nil { 1227 fmt.Printf("getRevisions() failed with '%s'\n", err) 1228 } 1229 } 1230 1231 func indexRelatedDocumentsTest() { 1232 err := indexRelatedDocuments("Produce") 1233 if err != nil { 1234 fmt.Printf("indexRelatedDocuments() failed with '%s'\n", err) 1235 } 1236 } 1237 1238 func queryRelatedDocumentsTest() { 1239 err := queryRelatedDocuments() 1240 if err != nil { 1241 fmt.Printf("queryRelatedDocuments() failed with '%s'\n", err) 1242 } 1243 } 1244 1245 func sessionTest() { 1246 err := session() 1247 if err != nil { 1248 fmt.Printf("sessionChapter() failed with '%s'\n", err) 1249 } 1250 } 1251 1252 func createDocumentTest() { 1253 err := createDocument("Hibernating Rhinos", "(+972)52-5486969", "New Contact Name", "New Contact Title") 1254 if err != nil { 1255 fmt.Printf("createDocument() failed with '%s'\n", err) 1256 } 1257 } 1258 1259 func editDocumentTest() { 1260 err := editDocument("New Company Name") 1261 if err != nil { 1262 fmt.Printf("editDocument() failed with '%s'\n", err) 1263 } 1264 } 1265 1266 func deleteDocumentTest() { 1267 err := deleteDocument("companies/1-A") 1268 if err != nil { 1269 fmt.Printf("deleteDocument() failed with '%s'\n", err) 1270 } 1271 } 1272 1273 func createRelatedDocumentsTest() { 1274 err := createRelatedDocuments("RavenDB", "Hibernating Rhinos", "(+972)52-54869696") 1275 if err != nil { 1276 fmt.Printf("createRelatedDocuments() failed with '%s'\n", err) 1277 } 1278 } 1279 1280 func loadRelatedDocumentsTest() { 1281 err := loadRelatedDocuments(12, "(+972)52-54869696") 1282 if err != nil { 1283 fmt.Printf("loadRelatedDocuments() failed with '%s'\n", err) 1284 } 1285 } 1286 1287 func storeAttachmentTest() { 1288 path := "pic.png" 1289 documentID := "companies/2-A" 1290 err := storeAttachment(documentID, path) 1291 if err != nil { 1292 fmt.Printf("storeAttachment() failed with '%s'\n", err) 1293 } else { 1294 fmt.Printf("stored file '%s' as attachment in a document with ID '%s'\n", path, documentID) 1295 } 1296 } 1297 1298 func enableRevisionsTest() { 1299 err := enableRevisions("Orders", "Companies") 1300 if err != nil { 1301 fmt.Printf("enableRevisions() failed with '%s'\n", err) 1302 } 1303 } 1304 1305 func mapReduceIndexTest() { 1306 err := mapReduceIndex("USA") 1307 if err != nil { 1308 fmt.Printf("mapReduceIndex() failed with '%s'\n", err) 1309 } 1310 } 1311 1312 var ( 1313 testFunctions = map[string]func(){ 1314 "createDocument": createDocumentTest, 1315 "session": sessionTest, 1316 "editDocument": editDocumentTest, 1317 "deleteDocument": deleteDocumentTest, 1318 "createRelatedDocuments": createRelatedDocumentsTest, 1319 "loadRelatedDocuments": loadRelatedDocumentsTest, 1320 "storeAttachment": storeAttachmentTest, 1321 "enableRevisions": enableRevisionsTest, 1322 "indexRelatedDocuments": indexRelatedDocumentsTest, 1323 "queryRelatedDocuments": queryRelatedDocumentsTest, 1324 "getRevisions": getRevisionsTest, 1325 "queryOverview": queryOverviewTest, 1326 "queryExample": queryExampleTest, 1327 "fullCollectionQuery": fullCollectionQueryTest, 1328 "queryByDocumentID": queryByDocumentIDTest, 1329 "queryFilterResultsBasic": queryFilterResultsBasicTest, 1330 "queryFilterResultsMultipleConditions": queryFilterResultsMultipleConditionsTest, 1331 "queryProjectingIndividualFields": queryProjectingIndividualFieldsTest, 1332 "queryProjectingUsingFunctions": queryProjectingUsingFunctionsTest, 1333 "staticIndexesOverview": staticIndexesOverviewTest, 1334 "mapIndex": mapIndexTest, 1335 "mapReduceIndex": mapReduceIndexTest, 1336 "autoMapIndex": autoMapIndexTest, 1337 "autoMapIndex2": autoMapIndex2Test, 1338 "fullTextSearchSingleField": fullTextSearchSingleFieldTest, 1339 "fullTextSearchMultipleField": fullTextSearchMultipleFieldTest, 1340 "createDatabase": createDatabaseTest, 1341 } 1342 ) 1343 1344 func usageAndExit() { 1345 fmt.Print(`To run: 1346 go run dive-into-raven/main.go <testName> 1347 e.g. 1348 go run dive-into-raven/main.go indexRelatedDocuments 1349 `) 1350 os.Exit(1) 1351 } 1352 1353 func must(err error, format string, args ...interface{}) { 1354 if err != nil { 1355 fmt.Printf(format, args...) 1356 panic(err) 1357 } 1358 } 1359 1360 func main() { 1361 if len(os.Args) != 2 { 1362 usageAndExit() 1363 } 1364 testNameArg := os.Args[1] 1365 testName := strings.TrimSuffix(testNameArg, "Test") 1366 testFn, ok := testFunctions[testName] 1367 if !ok { 1368 fmt.Printf("'%s' is not a known test function\n", testNameArg) 1369 usageAndExit() 1370 } 1371 1372 // setup optional logging 1373 setupLogging() 1374 defer finishLogging() 1375 1376 _, err := createTestDocumentStore() 1377 defer deleteTestDatabase() 1378 must(err, "createTestDocumentStore() failed with %s\n", err) 1379 fmt.Printf("Running %s\n", testNameArg) 1380 testFn() 1381 }