Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
certs
cmd/run_java_tests
dive-into-raven
examples
scripts
tests
.gitignore
.travis.yml
LICENSE
abstract_document_query.go
abstract_index_creation_task.go
advanced_session_extention_base.go
advanced_session_operations.go
after_save_changes_event_args.go
aggregation_document_query.go
aggregation_query_base.go
aggresive_cache_options.go
appveyor.yml
atomic_bool.go
atomic_integer.go
attachment_details.go
attachment_name.go
attachment_result.go
attachment_type.go
batch_command.go
batch_operation.go
batch_options.go
before_delete_event_args.go
before_query_event_args.go
before_store_event_args.go
bulk_insert_aborted_exception.go
bulk_insert_operation.go
character.go
circle_criteria.go
class_utils.go
clean_closeable.go
client_configuration.go
close_subclause_token.go
cluster_topology.go
cluster_topology_response.go
cmp_x_chg.go
codecov.yml
collection_statistics.go
command_type.go
compact_database_operation.go
compact_settings.go
compare_exchange_result.go
compare_exchange_value.go
compare_exchange_value_result_parser.go
completable_future.go
configure_revisions_operation.go
conflict_solver.go
connection_string.go
connection_string_type.go
constants.go
copier.go
create_database_operation.go
create_sample_data_operation.go
create_subscription_command.go
create_subscription_result.go
current_index_and_node.go
database_changes.go
database_promotion_status.go
database_put_result.go
database_record.go
database_record_with_etag.go
database_statistics.go
database_topology.go
declare_token.go
delete_attachment_command_data.go
delete_attachment_operation.go
delete_by_query_operation.go
delete_command_data.go
delete_compare_exchange_value_operation.go
delete_database_operation.go
delete_database_result.go
delete_document_command.go
delete_index_operation.go
delete_subscription_command.go
disable_index_operation.go
distinct_token.go
doc.go
document_change.go
document_change_types.go
document_conflict_exception.go
document_conventions.go
document_conventions_test.go
document_info.go
document_query.go
document_query_customization.go
document_query_helper.go
document_session.go
document_session_attachments.go
document_session_attachments_base.go
document_session_revisions.go
document_store.go
document_subscriptions.go
documents_by_id.go
documents_changes.go
drop_subscription_connection_command.go
duration.go
duration_serialization_test.go
dynamic_spatial_field.go
enable_index_operation.go
entity_to_json.go
errors.go
errors_test.go
event_handler.go
evict_items_from_cache_based_on_changes.go
exception_dispatcher.go
exceptions_utils.go
explain_query_command.go
external_replication.go
facet.go
facet_aggregation.go
facet_base.go
facet_builder.go
facet_options.go
facet_result.go
facet_setup.go
facet_term_sort_mode.go
facet_token.go
facet_value.go
field_indexing.go
field_storage.go
field_term_vector.go
fields_to_fetch_token.go
for_tests.go
from_token.go
generate_entity_id_on_the_client.go
generate_id.go
generate_id_test.go
generic_query_result.go
generic_range_facet.go
get_attachment_operation.go
get_client_configuration_operation.go
get_cluster_topology_command.go
get_collection_statistics_operation.go
get_compare_exchange_value_operation.go
get_compare_exchange_values_operation.go
get_conflicts_command.go
get_conflicts_result.go
get_database_names_operation.go
get_database_record_operation.go
get_database_topology_command.go
get_documents_command.go
get_documents_result.go
get_identities_operation.go
get_index_errors_operation.go
get_index_names_operation.go
get_index_operation.go
get_index_statistics_operation.go
get_indexes_operation.go
get_indexes_statistics_operation.go
get_indexing_status_operation.go
get_next_operation_id_command.go
get_operation_state_operation.go
get_request.go
get_response.go
get_revision_operation.go
get_revisions_bin_entry_command.go
get_revisions_command.go
get_server_wide_operation_state_operation.go
get_statistics_operation.go
get_subscription_state_command.go
get_subscriptions_command.go
get_subscriptions_result.go
get_tcp_info_command.go
get_terms_operation.go
go.mod
go.sum
group_by.go
group_by_count_token.go
group_by_document_query.go
group_by_field.go
group_by_key_token.go
group_by_method.go
group_by_sum_token.go
group_by_token.go
handling_maps.md
hash_calculator.go
head_attachment_command.go
head_document_command.go
hi_lo_id_generator.go
hi_lo_result.go
hi_lo_return_command.go
http.go
http_cache.go
http_cache_item.go
http_extensions.go
i_command_data.go
i_lazy_operation.go
i_maintenance_operation.go
i_more_like_this_builder_base.go
i_more_like_this_builder_for_document_query.go
i_more_like_this_operations.go
i_operation.go
i_server_operation.go
id_type_and_name.go
in_memory_document_session_operations.go
includes_util.go
index_change.go
index_change_types.go
index_configuration.go
index_creation.go
index_definition.go
index_definition_builder.go
index_errors.go
index_field_options.go
index_has_changed_operation.go
index_information.go
index_lock_mode.go
index_priority.go
index_query.go
index_query_base.go
index_query_content.go
index_query_with_parameters.go
index_running_status.go
index_state.go
index_stats.go
index_type.go
indexing_error.go
indexing_status.go
inflect.go
intersect_marker_token.go
java_script_array.go
json_array_result.go
json_extensions.go
json_operation.go
json_util.go
kill_operation_command.go
lazy.go
lazy_aggregation_query_operation.go
lazy_load_operation.go
lazy_multi_loader_with_include.go
lazy_query_operation.go
lazy_session_operations.go
lazy_starts_with_operation.go
lazy_suggestion_query_operation.go
leader_stamp.go
load_operation.go
load_starting_with_operation.go
load_token.go
maintenance_operation_executor.go
map_util.go
metadata_as_dictionary.go
method_call.go
modify_ongoing_task_result.go
more_like_this_base.go
more_like_this_builder.go
more_like_this_options.go
more_like_this_query_result.go
more_like_this_scope.go
more_like_this_stop_words.go
more_like_this_token.go
more_like_this_using_any_document.go
more_like_this_using_document.go
more_like_this_using_document_for_document_query.go
multi_database_hi_lo_id_generator.go
multi_get_command.go
multi_get_operation.go
multi_loader_with_include.go
multi_type_hi_lo_id_generator.go
negate_token.go
next_hi_lo_command.go
next_identity_for_command.go
node_id.go
node_selector.go
object_set.go
open_subclause_token.go
operation.go
operation_exception_result.go
operation_executor.go
operation_id_result.go
operation_status_change.go
order_by_token.go
ordering_type.go
parameters.go
patch_by_query_operation.go
patch_command_data.go
patch_operation.go
patch_request.go
patch_result.go
patch_status.go
point_field.go
porting_notes.md
put_attachment_command_data.go
put_attachment_operation.go
put_client_configuration_operation.go
put_command_data_with_json.go
put_compare_exchange_value_operation.go
put_connection_string_operation.go
put_connection_string_result.go
put_document_command.go
put_index_result.go
put_indexes_operation.go
put_indexes_response.go
put_result.go
query_command.go
query_data.go
query_field_util.go
query_operation.go
query_operation_options.go
query_operator.go
query_operator_token.go
query_result.go
query_result_base.go
query_statistics.go
query_stream_command.go
query_token.go
range_builder.go
range_builder_test.go
range_facet.go
raven_command.go
raven_command_response_type.go
raven_connection_string.go
raw_document_query.go
read_balance_behavior.go
readme-dev.md
readme.md
reflect.go
reflect_test.go
replication_node.go
request_executor.go
requests_helpers.go
reset_index_operation.go
response_dispose_handling.go
response_time_information.go
revision.go
revisions_collection_configuration.go
revisions_configuration.go
script_resolver.go
search_operator.go
seed_identity_for_command.go
semaphore.go
server_node.go
server_operation_executor.go
server_wide_operation.go
session_created_event_args.go
session_info.go
session_options.go
set_indexes_lock_operation.go
set_indexes_priority_operation.go
shape_token.go
size.go
spatial_criteria.go
spatial_criteria_factory.go
spatial_field_type.go
spatial_options.go
spatial_options_factory.go
spatial_relation.go
spatial_search_strategy.go
spatial_units.go
start_index_operation.go
start_indexing_operation.go
starts_with_args.go
stop_index_operation.go
stop_indexing_operation.go
stream_command.go
stream_operation.go
stream_query_statistics.go
stream_result.go
stream_result_response.go
string_array.go
string_array_test.go
string_distance_types.go
string_utils.go
subscription_batch.go
subscription_connection_client_message.go
subscription_connection_server_message.go
subscription_creation_options.go
subscription_opening_strategy.go
subscription_state.go
subscription_state_with_node_details.go
subscription_tryout.go
subscription_worker.go
subscription_worker_options.go
suggest_token.go
suggestion_base.go
suggestion_builder.go
suggestion_document_query.go
suggestion_options.go
suggestion_query_base.go
suggestion_result.go
suggestion_sort_mode.go
suggestion_with_term.go
suggestion_with_terms.go
tcp_connection_header_message.go
tcp_connection_header_response.go
tcp_connection_info.go
tcp_connection_status.go
tcp_negotiate_parameters.go
tcp_negotiation.go
tcp_utils.go
terms_query_result.go
time.go
time_test.go
time_utils.go
topology.go
true_token.go
update_external_replication_operation.go
url_utils.go
util.go
util_test.go
uuid.go
where_operator.go
where_params.go
where_token.go
wkt_criteria.go
wkt_field.go

readme.md

Linux build Status Windows build status

This is information on how to use the library. For docs on working on the library itself see readme-dev.md.

This library requires go 1.11 or later.

API reference: https://godoc.org/github.com/ravendb/ravendb-go-client

This library is in beta state. All the basic functionality works and passes extensive test suite, but the API for more esoteric features might change.

If you encounter bugs, have suggestions or feature requests, please open an issue.

Documentation

To learn basics of RavenDB, read RavenDB Documentation or Dive into RavenDB.

Getting started

Full source code of those examples is in examples directory.

To run a a specific example, e.g. crudStore, you can run:

  • .\scripts\run_example.ps1 crudStore : works on mac / linux if you have powershell installed
  • go run examples\log.go examples\main.go crudStore : on mac / linux change paths to examples/log.go etc.
  1. Import the package
import (
	ravendb "github.com/ravendb/ravendb-go-client"
)
  1. Initialize document store (you should have one DocumentStore instance per application)
func getDocumentStore(databaseName string) (*ravendb.DocumentStore, error) {
	serverNodes := []string{"http://live-test.ravendb.net"}
	store := ravendb.NewDocumentStore(serverNodes, databaseName)
	if err := store.Initialize(); err != nil {
		return nil, err
	}
	return store, nil
}
  1. Open a session and close it when done
session, err = store.OpenSession()
if err != nil {
	log.Fatalf("store.OpenSession() failed with %s", err)
}
// ... use session
session.Close()
  1. Call SaveChanges() to persist changes in a session:
var e *northwind.Employee
err = session.Load(&e, "employees/7-A")
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}

origName := e.FirstName
e.FirstName = e.FirstName + "Changed"
err = session.Store(e)
if err != nil {
    log.Fatalf("session.Store() failed with %s\n", err)
}

err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with %s\n", err)
}

var e2 *northwind.Employee
err = session.Load(&e2, "employees/7-A")
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}
fmt.Printf("Updated Employee.FirstName from '%s' to '%s'\n", origName, e2.FirstName)

See loadUpdateSave() in examples/main.go for full example.

CRUD example

Storing documents

product := &northwind.Product{
    Name:         "iPhone X",
    PricePerUnit: 999.99,
    Category:     "electronis",
    ReorderLevel: 15,
}
err = session.Store(product)
if err != nil {
    log.Fatalf("session.Store() failed with %s\n", err)
}

See crudStore() in examples/main.go for full example.

Loading documents

var e *northwind.Employee
err = session.Load(&e, "employees/7-A")
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}
fmt.Printf("employee: %#v\n", e)

See crudLoad() in examples/main.go for full example.

Loading documents with includes

Some entities point to other entities via id. For example Employee has ReportsTo field which is an id of Employee that it reports to.

To improve performance by minimizing number of server requests, we can use includes functionality to load such linked entities.

// load employee with id "employees/7-A" and entity whose id is ReportsTo
var e *northwind.Employee
err = session.Include("ReportsTo").Load(&e, "employees/5-A")
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}
if e.ReportsTo == "" {
    fmt.Printf("Employee with id employees/5-A doesn't report to anyone\n")
    return
}

numRequests := session.GetNumberOfRequests()
var reportsTo *northwind.Employee
err = session.Load(&reportsTo, e.ReportsTo)
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}
if numRequests != session.GetNumberOfRequests() {
    fmt.Printf("Something's wrong, this shouldn't send a request to the server\n")
} else {
    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")
}

See crudLoadWithInclude() in examples/main.go for full example.

Updating documents

// load entity from the server
var p *northwind.Product
err = session.Load(&p, productID)
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}

// update price
origPrice = p.PricePerUnit
newPrice = origPrice + 10
p.PricePerUnit = newPrice
err = session.Store(p)
if err != nil {
    log.Fatalf("session.Store() failed with %s\n", err)
}

// persist changes on the server
err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with %s\n", err)
}

See crudUpdate() in examples/main.go for full example.

Deleting documents

Delete using entity:

// ... store a product and remember its id in productID

var p *northwind.Product
err = session.Load(&p, productID)
if err != nil {
    log.Fatalf("session.Load() failed with %s\n", err)
}

err = session.Delete(p)
if err != nil {
    log.Fatalf("session.Delete() failed with %s\n", err)
}

err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with %s\n", err)
}

See crudDeleteUsingEntity() in examples/main.go for full example.

Entity must be a value that we either stored in the database in the current session via Store() or loaded from database using Load(), LoadMulti(), query etc.

Delete using id:

// ... store a product and remember its id in productID

err = session.DeleteByID(productID, "")
if err != nil {
    log.Fatalf("session.Delete() failed with %s\n", err)
}

err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with %s\n", err)
}

Second argument to DeleteByID is optional changeVector, for fine-grain concurrency control.

See crudDeleteUsingID() in examples/main.go for full example.

Querying documents

Selecting what to query

First you need to decide what to query.

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.

You can query by collection name:

q := session.QueryCollection("employees")

See queryCollectionByName() in examples/main.go for full example.

To get a collection name for a given type use ravendb.GetCollectionNameDefault(&MyStruct{}).

You can query a collection for a given type:

tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)

See queryCollectionByType() in examples/main.go for full example.

You can query an index:

q := session.QueryIndex("Orders/ByCompany")

See queryIndex() in examples/main.go for full example.

Limit what is returned

tp := reflect.TypeOf(&northwind.Product{})
q := session.QueryCollectionForType(tp)

q = q.WaitForNonStaleResults(0)
q = q.WhereEquals("Name", "iPhone X")
q = q.OrderBy("PricePerUnit")
q = q.Take(2) // limit to 2 results

See queryComplex() in examples/main.go for full example.

Obtain the results

You can get all matching results:

var products []*northwind.Product
err = q.GetResults(&products)

See queryComplex() in examples/main.go for full example.

You can get just first one:

var first *northwind.Employee
err = q.First(&first)

See queryFirst() in examples/main.go for full example.

Overview of DocumentQuery methods

SelectFields() - projections using a single field

// RQL equivalent: from employees select FirstName
q = q.SelectFields(reflect.TypeOf(""), "FirstName")

var names []string
err = q.GetResults(&names)

See querySelectSingleField() in examples/main.go for full example.

SelectFields() - projections using multiple fields

type employeeNameTitle struct {
	FirstName string
	Title     string
}

// RQL equivalent: from employees select FirstName, Title
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.SelectFields(reflect.TypeOf(&employeeNameTitle{}), "FirstName", "Title")

See querySelectFields() in examples/main.go for full example.

Distinct()

// RQL equivalent: from employees select distinct Title
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.SelectFields(reflect.TypeOf(""), "Title")
q = q.Distinct()

See queryDistinct() in examples/main.go for full example.

WhereEquals() / WhereNotEquals()

// RQL equivalent: from employees where Title = 'Sales Representative'
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereEquals("Title", "Sales Representative")

See queryEquals() in examples/main.go for full example.

WhereIn

// RQL equivalent: from employees where Title in ['Sales Representative', 'Sales Manager']
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereIn("Title", []interface{}{"Sales Representative", "Sales Manager"})

See queryIn() in examples/main.go for full example.

WhereStartsWith() / WhereEndsWith()

// RQL equivalent:
// from employees where startsWith('Ro')
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereStartsWith("FirstName", "Ro")

See queryStartsWith() and queryEndsWith in examples/main.go for full example.

WhereBetween()

// RQL equivalent:
// from orders where Freight between 11 and 13
tp := reflect.TypeOf(&northwind.Order{})
q := session.QueryCollectionForType(tp)
q = q.WhereBetween("Freight", 11, 13)

See queryBetween() in examples/main.go for full example.

WhereGreaterThan() / WhereGreaterThanOrEqual() / WhereLessThan() / WhereLessThanOrEqual()

// RQL equivalent:
// from orders where Freight Freight > 11
tp := reflect.TypeOf(&northwind.Order{})
q := session.QueryCollectionForType(tp)
// can also be WhereGreaterThanOrEqual(), WhereLessThan(), WhereLessThanOrEqual()
q = q.WhereGreaterThan("Freight", 11)

See queryGreater() in examples/main.go for full example.

WhereExists()

Checks if the field exists.

// RQL equivalent:
// from employees where exists ("ReportsTo")
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereExists("ReportsTo")

See queryExists() in examples/main.go for full example.

ContainsAny() / ContainsAll()

// RQL equivalent:
// from employees where FirstName in ("Anne", "Nancy")
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.ContainsAny("FirstName", []interface{}{"Anne", "Nancy"})

See queryContainsAny() in examples/main.go for full example.

Search()

Performs full-text search:

// RQL equivalent:
// from employees where search(FirstName, 'Anne Nancy')
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.Search("FirstName", "Anne Nancy")

See querySearch() in examples/main.go for full example.

OpenSubclause() / CloseSubclause()

// RQL equivalent:
// from employees where (FirstName = 'Steven') or (Title = 'Sales Representative' and LastName = 'Davolio')
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereEquals("FirstName", "Steven")
q = q.OrElse()
q = q.OpenSubclause()
q = q.WhereEquals("Title", "Sales Representative")
q = q.WhereEquals("LastName", "Davolio")
q = q.CloseSubclause()

See querySubclause() in examples/main.go for full example.

Not()

// RQL equivalent:
// from employees where not FirstName = 'Steven'
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.Not()
q = q.WhereEquals("FirstName", "Steven")

See queryNot() in examples/main.go for full example.

AndAlso() / OrElse()

// RQL equivalent:
// from employees where FirstName = 'Steven' or FirstName  = 'Nancy'
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereEquals("FirstName", "Steven")
// can also be AndElse()
q = q.OrElse()
q = q.WhereEquals("FirstName", "Nancy")

See queryOrElse() in examples/main.go for full example.

UsingDefaultOperator()

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.

OrderBy() / RandomOrdering()

// RQL equivalent:
// from employees order by FirstName
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
// can also be RandomOrdering()
q = q.OrderBy("FirstName")

See queryOrderBy() in examples/main.go for full example.

Take()

// RQL equivalent:
// from employees order by FirstName desc
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.OrderByDescending("FirstName")
q = q.Take(2)

See queryTake() in examples/main.go for full example.

Skip()

// RQL equivalent:
// from employees order by FirstName desc
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.OrderByDescending("FirstName")
q = q.Take(2)
q = q.Skip(1)

See querySkip() in examples/main.go for full example.

Getting query statistics

To obtain query statistics use Statistics() method.

var stats *ravendb.QueryStatistics
tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
q = q.WhereGreaterThan("FirstName", "Bernard")
q = q.OrderByDescending("FirstName")
q.Statistics(&stats)

Statistics:

Statistics:
{IsStale:           false,
 DurationInMs:      0,
 TotalResults:      7,
 SkippedResults:    0,
 Timestamp:         2019-02-13 02:57:31.5226409 +0000 UTC,
 IndexName:         "Auto/employees/ByLastNameAndReportsToAndSearch(FirstName)AndTitle",
 IndexTimestamp:    2019-02-13 02:57:31.5226409 +0000 UTC,
 LastQueryTime:     2019-02-13 03:50:25.7602429 +0000 UTC,
 TimingsInMs:       {},
 ResultEtag:        7591488513381790088,
 ResultSize:        0,
 ScoreExplanations: {}}

See queryStatistics() in examples/main.go for full example.

GetResults() / First() / Single() / Count()

GetResults() - returns all results

First() - first result

Single() - first result, returns error if there's more entries

Count() - returns the number of the results (not affected by take())

See queryFirst(), querySingle() and queryCount() in examples/main.go for full example.

Attachments

Store attachments

fileStream, err := os.Open(path)
if err != nil {
    log.Fatalf("os.Open() failed with '%s'\n", err)
}
defer fileStream.Close()

fmt.Printf("new employee id: %s\n", e.ID)
err = session.Advanced().Attachments().Store(e, "photo.png", fileStream, "image/png")

// could also be done using document id
// err = session.Advanced().Attachments().Store(e.ID, "photo.png", fileStream, "image/png")

if err != nil {
    log.Fatalf("session.Advanced().Attachments().Store() failed with '%s'\n", err)
}

err = session.SaveChanges()

See storeAttachments() in examples/main.go for full example.

Get attachments

attachment, err := session.Advanced().Attachments().Get(docID, "photo.png")
if err != nil {
    log.Fatalf("session.Advanced().Attachments().Get() failed with '%s'\n", err)
}
defer attachment.Close()
fmt.Print("Attachment details:\n")
pretty.Print(attachment.Details)
// read attachment data
// attachment.Data is io.Reader
var attachmentData bytes.Buffer
n, err := io.Copy(&attachmentData, attachment.Data)
if err != nil {
    log.Fatalf("io.Copy() failed with '%s'\n", err)
}
fmt.Printf("Attachment size: %d bytes\n", n)

Attachment details:

{AttachmentName: {Name:        "photo.png",
                  Hash:        "MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=",
                  ContentType: "image/png",
                  Size:        4579},
 ChangeVector:   "A:4905-dMAeI9ANZ06DOxCRLnSmNw",
 DocumentID:     "employees/44-A"}
Attachment size: 4579 bytes

See getAttachments() in examples/main.go for full example.

Check if attachment exists

name := "photo.png"
exists, err := session.Advanced().Attachments().Exists(docID, name)
if err != nil {
    log.Fatalf("session.Advanced().Attachments().Exists() failed with '%s'\n", err)
}

See checkAttachmentExists() in examples/main.go for full example.

Get attachment names

names, err := session.Advanced().Attachments().GetNames(doc)
if err != nil {
    log.Fatalf("session.Advanced().Attachments().GetNames() failed with '%s'\n", err)
}

Attachment names:

[{Name:        "photo.png",
  Hash:        "MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=",
  ContentType: "image/png",
  Size:        4579}]

See getAttachmentNames() in examples/main.go for full example.

Bulk insert

When storing multiple documents, use bulk insertion.

bulkInsert := store.BulkInsert("")

names := []string{"Anna", "Maria", "Miguel", "Emanuel", "Dayanara", "Aleida"}
for _, name := range names {
    e := &northwind.Employee{
        FirstName: name,
    }
    id, err := bulkInsert.Store(e, nil)
    if err != nil {
        log.Fatalf("bulkInsert.Store() failed with '%s'\n", err)
    }
}
// flush data and finish
err = bulkInsert.Close()

See bulkInsert() in examples/main.go for full example.

Observing changes in the database

Listen for database changes e.g. document changes.

changes := store.Changes("")

err = changes.EnsureConnectedNow()
if err != nil {
    log.Fatalf("changes.EnsureConnectedNow() failed with '%s'\n", err)
}

cb := func(change *ravendb.DocumentChange) {
    fmt.Print("change:\n")
    pretty.Print(change)
}
docChangesCancel, err := changes.ForAllDocuments(cb)
if err != nil {
    log.Fatalf("changes.ForAllDocuments() failed with '%s'\n", err)
}

defer docChangesCancel()

e := &northwind.Employee{
    FirstName: "Jon",
    LastName:  "Snow",
}
err = session.Store(e)
if err != nil {
    log.Fatalf("session.Store() failed with '%s'\n", err)
}

err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with '%s'\n", err)
}
// cb should now be called notifying there's a new document

Example change:

{Type:           "Put",
 ID:             "Raven/Hilo/employees",
 CollectionName: "@hilo",
 ChangeVector:   "A:4892-bJERJNLunE+4xQ/yDEuk1Q"}

See changes() in examples/main.go for full example.

Streaming

Streaming allows interating over documents matching certain criteria.

It's useful when there's a large number of results as it limits memory use by reading documents in batches (as opposed to all at once).

Stream documents with ID prefix

Here we iterate over all documents in products collection:

args := &ravendb.StartsWithArgs{
    StartsWith: "products/",
}
iterator, err := session.Advanced().Stream(args)
if err != nil {
    log.Fatalf("session.Advanced().Stream() failed with '%s'\n", err)
}
for {
    var p *northwind.Product
    streamResult, err := iterator.Next(&p)
    if err != nil {
        // io.EOF means there are no more results
        if err == io.EOF {
            err = nil
        } else {
            log.Fatalf("iterator.Next() failed with '%s'\n", err)
        }
        break
    }
    // handle p
}

See streamWithIDPrefix() in examples/main.go for full example.

This returns:

streamResult:
{ID:           "products/1-A",
 ChangeVector: "A:96-bJERJNLunE+4xQ/yDEuk1Q",
 Metadata:     {},
 Document:     ... same as product but as map[string]interface{} ...

product:
{ID:              "products/1-A",
 Name:            "Chai",
 Supplier:        "suppliers/1-A",
 Category:        "categories/1-A",
 QuantityPerUnit: "10 boxes x 20 bags",
 PricePerUnit:    18,
 UnitsInStock:    1,
 UnistsOnOrder:   0,
 Discontinued:    false,
 ReorderLevel:    10}

Stream query results

tp := reflect.TypeOf(&northwind.Product{})
q := session.QueryCollectionForType(tp)
q = q.WhereGreaterThan("PricePerUnit", 15)
q = q.OrderByDescending("PricePerUnit")

iterator, err := session.Advanced().StreamQuery(q, nil)
if err != nil {
    log.Fatalf("session.Advanced().StreamQuery() failed with '%s'\n", err)
}
// rest of processing as above

See streamQueryResults() in examples/main.go for full example.

Revisions

Note: make sure to enable revisions in a given store using NewConfigureRevisionsOperation operation.

e := &northwind.Employee{
    FirstName: "Jon",
    LastName:  "Snow",
}
err = session.Store(e)
if err != nil {
    log.Fatalf("session.Store() failed with '%s'\n", err)
}
err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with '%s'\n", err)
}

// modify document to create a new revision
e.FirstName = "Jhonny"
err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with '%s'\n", err)
}

var revisions []*northwind.Employee
err = session.Advanced().Revisions().GetFor(&revisions, e.ID)

See revisions() in examples/main.go for full example.

Returns:

[{ID:          "employees/43-A",
  LastName:    "Snow",
  FirstName:   "Jhonny",
  Title:       "",
  Address:     nil,
  HiredAt:     {},
  Birthday:    {},
  HomePhone:   "",
  Extension:   "",
  ReportsTo:   "",
  Notes:       [],
  Territories: []},
 {ID:          "employees/43-A",
  LastName:    "Snow",
  FirstName:   "Jon",
  Title:       "",
  Address:     nil,
  HiredAt:     {},
  Birthday:    {},
  HomePhone:   "",
  Extension:   "",
  ReportsTo:   "",
  Notes:       [],
  Territories: []}]

Suggestions

Suggestions provides similarity queries. Here we're asking for FirstName values similar to Micael and the database suggests Michael.

index := ravendb.NewIndexCreationTask("EmployeeIndex")
index.Map = "from doc in docs.Employees select new { doc.FirstName }"
index.Suggestion("FirstName")

err = store.ExecuteIndex(index, "")
if err != nil {
    log.Fatalf("store.ExecuteIndex() failed with '%s'\n", err)
}

tp := reflect.TypeOf(&northwind.Employee{})
q := session.QueryCollectionForType(tp)
su := ravendb.NewSuggestionWithTerm("FirstName")
su.Term = "Micael"
suggestionQuery := q.SuggestUsing(su)
results, err := suggestionQuery.Execute()

See suggestions() in examples/main.go for full example.

Returns:

{FirstName: {Name:        "FirstName",
             Suggestions: ["michael"]}}

Advanced patching

To update documents more efficiently than sending the whole document, you can patch just a given field or atomically add/substract values of numeric fields.

err = session.Advanced().IncrementByID(product.ID, "PricePerUnit", 15)
if err != nil {
    log.Fatalf("session.Advanced().IncrementByID() failed with %s\n", err)
}

err = session.Advanced().Patch(product, "Category", "expensive products")
if err != nil {
    log.Fatalf("session.Advanced().PatchEntity() failed with %s\n", err)
}

err = session.SaveChanges()
if err != nil {
    log.Fatalf("session.SaveChanges() failed with %s\n", err)
}

See advancedPatching() in examples/main.go for full example.

Subscriptions

opts := ravendb.SubscriptionCreationOptions{
    Query: "from Products where PricePerUnit > 17 and PricePerUnit < 19",
}
subscriptionName, err := store.Subscriptions().Create(&opts, "")
if err != nil {
    log.Fatalf("store.Subscriptions().Create() failed with %s\n", err)
}
wopts := ravendb.NewSubscriptionWorkerOptions(subscriptionName)
worker, err := store.Subscriptions().GetSubscriptionWorker(tp, wopts, "")
if err != nil {
    log.Fatalf("store.Subscriptions().GetSubscriptionWorker() failed with %s\n", err)
}

results := make(chan *ravendb.SubscriptionBatch, 16)
cb := func(batch *ravendb.SubscriptionBatch) error {
    results <- batch
    return nil
}
err = worker.Run(cb)
if err != nil {
    log.Fatalf("worker.Run() failed with %s\n", err)
}

// wait for first batch result
select {
case batch := <-results:
    fmt.Print("Batch of subscription results:\n")
    pretty.Print(batch)
case <-time.After(time.Second * 5):
    fmt.Printf("Timed out waiting for first subscription batch\n")

}

_ = worker.Close()

See subscriptions() in examples/main.go for full example.

You can’t perform that action at this time.