diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9bb47fa3..de127ca5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,17 +34,21 @@ analyze: - dart pub get --directory=generator - dart pub get --directory=objectbox - dart pub get --directory=objectbox_test + - dart pub get --directory=objectbox/example/dart-native/vectorsearch_cities # Generate code - cd benchmark - dart run build_runner build - cd ../objectbox_test - dart run build_runner build - - cd .. + - cd ../objectbox/example/dart-native/vectorsearch_cities + - dart run build_runner build + - cd ../../../.. # back to repo root # Analyze Dart packages - dart analyze benchmark - dart analyze generator - dart analyze objectbox - dart analyze objectbox_test + - dart analyze objectbox/example/dart-native/vectorsearch_cities # Check formatting of all packages - dart format --set-exit-if-changed --fix . @@ -120,3 +124,18 @@ coverage: artifacts: paths: - objectbox/coverage/html/ + +# For the Dart Native example compiles and runs the executable (analysis and code formatting is +# checked by analyze job). +dart-examples-test: + extends: .cache + stage: test + tags: [ x64, linux, docker ] + image: dart:$DART_VERSION + script: + - cd objectbox/example/dart-native/vectorsearch_cities + - dart pub get + - dart run build_runner build + - ../../../../install.sh + - dart compile exe bin/vectorsearch_cities.dart + - ./bin/vectorsearch_cities.exe diff --git a/objectbox/CHANGELOG.md b/objectbox/CHANGELOG.md index 6c59aa8e..24ff0d65 100644 --- a/objectbox/CHANGELOG.md +++ b/objectbox/CHANGELOG.md @@ -1,6 +1,7 @@ ## latest * Export `ObjectWithScore` and `IdWithScore` used by the new find with score `Query` methods. [#637] +* Add simple `vectorsearch_cities` Dart Native example application. ## 4.0.0 (2024-05-15) diff --git a/objectbox/example/README.md b/objectbox/example/README.md index 1b1e638c..737a25a1 100644 --- a/objectbox/example/README.md +++ b/objectbox/example/README.md @@ -3,6 +3,8 @@ ObjectBox Examples There are several example apps and tutorials available: +* [vectorsearch_cities](dart-native/vectorsearch_cities): a Dart Native example app using Vector + Search to find neighbors of cities. * [objectbox_demo_relations](flutter/objectbox_demo_relations): our main Flutter example app showing all basics and how to use relations. * [event_management_tutorial](flutter/event_management_tutorial): an event management Flutter app diff --git a/objectbox/example/dart-native/vectorsearch_cities/.gitignore b/objectbox/example/dart-native/vectorsearch_cities/.gitignore new file mode 100644 index 00000000..3a857904 --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/.gitignore @@ -0,0 +1,3 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ diff --git a/objectbox/example/dart-native/vectorsearch_cities/README.md b/objectbox/example/dart-native/vectorsearch_cities/README.md new file mode 100644 index 00000000..aa663a14 --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/README.md @@ -0,0 +1,8 @@ +# Vector-Search Example: Cities + +This is a simple example application to demonstrate the Vector Search feature of ObjectBox. +It searches for nearest neighbors of a city. + +## Docs +- [Getting started with ObjectBox](https://docs.objectbox.io/getting-started) +- [ANN Vector Search](https://docs.objectbox.io/ann-vector-search) diff --git a/objectbox/example/dart-native/vectorsearch_cities/analysis_options.yaml b/objectbox/example/dart-native/vectorsearch_cities/analysis_options.yaml new file mode 100644 index 00000000..dee8927a --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/objectbox/example/dart-native/vectorsearch_cities/bin/vectorsearch_cities.dart b/objectbox/example/dart-native/vectorsearch_cities/bin/vectorsearch_cities.dart new file mode 100644 index 00000000..22db1d6a --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/bin/vectorsearch_cities.dart @@ -0,0 +1,17 @@ +import 'package:vectorsearch_cities/objectbox.dart'; + +void main(List arguments) { + final objectBox = ObjectBox.create(); + + // Retrieve IDs + final resultIds = objectBox.findTwoClosestNeighborsIds(); + for (final result in resultIds) { + print("City ID: ${result.id}, distance: ${result.score}"); + } + + // Retrieve objects + final results = objectBox.findTwoClosestNeighbors(); + for (final result in results) { + print("City: ${result.object.name}, distance: ${result.score}"); + } +} diff --git a/objectbox/example/dart-native/vectorsearch_cities/lib/model.dart b/objectbox/example/dart-native/vectorsearch_cities/lib/model.dart new file mode 100644 index 00000000..0910694e --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/lib/model.dart @@ -0,0 +1,15 @@ +import 'package:objectbox/objectbox.dart'; + +@Entity() +class City { + @Id() + int id = 0; + + String? name; + + @HnswIndex(dimensions: 2) + @Property(type: PropertyType.floatVector) + List? location; + + City(this.name, this.location); +} diff --git a/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox-model.json b/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox-model.json new file mode 100644 index 00000000..4fa2e002 --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox-model.json @@ -0,0 +1,44 @@ +{ + "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", + "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", + "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", + "entities": [ + { + "id": "1:4473667649417503248", + "lastPropertyId": "3:6086893156295683893", + "name": "City", + "properties": [ + { + "id": "1:7234981322630746044", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:2260839727248414810", + "name": "name", + "type": 9 + }, + { + "id": "3:6086893156295683893", + "name": "location", + "type": 28, + "flags": 8, + "indexId": "1:145739237546482940" + } + ], + "relations": [] + } + ], + "lastEntityId": "1:4473667649417503248", + "lastIndexId": "1:145739237546482940", + "lastRelationId": "0:0", + "lastSequenceId": "0:0", + "modelVersion": 5, + "modelVersionParserMinimum": 5, + "retiredEntityUids": [], + "retiredIndexUids": [], + "retiredPropertyUids": [], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox.dart b/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox.dart new file mode 100644 index 00000000..6829c509 --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/lib/objectbox.dart @@ -0,0 +1,69 @@ +import 'model.dart'; +import 'objectbox.g.dart'; + +/// Provides access to the ObjectBox Store throughout the app. +class ObjectBox { + /// The Store of this app. + late final Store _store; + + late final Box _cityBox; + + ObjectBox._create(this._store) { + _cityBox = Box(_store); + + if (_cityBox.isEmpty()) { + _putCityData(); + } + } + + /// Create an instance of ObjectBox to use throughout the app. + static ObjectBox create() { + // Note: set macosApplicationGroup for sandboxed macOS applications, see the + // Store documentation for details. + + // Store openStore() {...} is defined in the generated objectbox.g.dart + final store = openStore( + directory: "obx-demo-vectorsearch-cities", + macosApplicationGroup: "objectbox.demo"); + return ObjectBox._create(store); + } + + _putCityData() { + _cityBox.putMany([ + City("Barcelona", [41.385063, 2.173404]), + City("Nairobi", [-1.292066, 36.821945]), + City("Salzburg", [47.809490, 13.055010]), + ]); + } + + Query _queryTwoClosestNeighbors() { + final madrid = [40.416775, -3.703790]; // query vector + // Prepare a Query object to search for the 2 closest neighbors: + final query = + _cityBox.query(City_.location.nearestNeighborsF32(madrid, 2)).build(); + + // Combine with other conditions as usual + // ignore: unused_local_variable + final queryCombined = _cityBox + .query(City_.location + .nearestNeighborsF32(madrid, 2) + .and(City_.name.startsWith("B"))) + .build(); + + return query; + } + + List findTwoClosestNeighborsIds() { + final query = _queryTwoClosestNeighbors(); + final results = query.findIdsWithScores(); + query.close(); + return results; + } + + List> findTwoClosestNeighbors() { + final query = _queryTwoClosestNeighbors(); + final results = query.findWithScores(); + query.close(); + return results; + } +} diff --git a/objectbox/example/dart-native/vectorsearch_cities/pubspec.yaml b/objectbox/example/dart-native/vectorsearch_cities/pubspec.yaml new file mode 100644 index 00000000..ddba653b --- /dev/null +++ b/objectbox/example/dart-native/vectorsearch_cities/pubspec.yaml @@ -0,0 +1,21 @@ +name: vectorsearch_cities +description: Vector Search Example with Cities. +version: 1.0.0 + +environment: + sdk: ^2.18.6 + +dependencies: + objectbox: ^4.0.0 + +dev_dependencies: + build_runner: ^2.4.9 + lints: ^3.0.0 + objectbox_generator: any + +# Note: these overrides are only for ObjectBox internal development, don't use them in your app. +dependency_overrides: + objectbox: + path: ../../../../objectbox + objectbox_generator: + path: ../../../../generator diff --git a/tool/init.sh b/tool/init.sh index 96bc371f..4a4bd3de 100755 --- a/tool/init.sh +++ b/tool/init.sh @@ -40,6 +40,7 @@ initialize dart objectbox initialize dart generator initialize dart objectbox_test generate initialize dart benchmark generate +initialize dart objectbox/example/dart-native/vectorsearch_cities generate initialize flutter objectbox/example/flutter/objectbox_demo generate initialize flutter objectbox/example/flutter/objectbox_demo_relations generate initialize flutter objectbox/example/flutter/objectbox_demo_sync generate diff --git a/tool/pubdev-links.sh b/tool/pubdev-links.sh index d79fa187..05f20c7f 100755 --- a/tool/pubdev-links.sh +++ b/tool/pubdev-links.sh @@ -6,6 +6,7 @@ echo "Setting pub.dev specific links" update objectbox/README.md "s|CHANGELOG.md|https://pub.dev/packages/objectbox/changelog|g" update objectbox/README.md "s|../CONTRIBUTING.md|https://github.com/objectbox/objectbox-dart/blob/main/CONTRIBUTING.md|g" # Links generated by pub.dev are missing "objectbox" path, so replace with absolute link. +update objectbox/example/README.md "s|dart-native/vectorsearch_cities|https://github.com/objectbox/objectbox-dart/tree/main/objectbox/example/dart-native/vectorsearch_cities|g" update objectbox/example/README.md "s|flutter/objectbox_demo|https://github.com/objectbox/objectbox-dart/tree/main/objectbox/example/flutter/objectbox_demo|g" #update objectbox/example/README.md "s|flutter/objectbox_demo_relations|https://github.com/objectbox/objectbox-dart/tree/main/objectbox/example/flutter/objectbox_demo_relations|g" update objectbox/example/README.md "s|flutter/event_management_tutorial|https://github.com/objectbox/objectbox-dart/tree/main/objectbox/example/flutter/event_management_tutorial|g" diff --git a/tool/set-version.sh b/tool/set-version.sh index 1634fe0d..17f3849c 100755 --- a/tool/set-version.sh +++ b/tool/set-version.sh @@ -21,6 +21,7 @@ versionDartExpr="s/current = \".*\"/current = \"${version}\"/g" update generator/lib/src/version.dart "${versionDartExpr}" dependencyHigherExpr="s/objectbox: \^.*/objectbox: ^${version}/g" +update objectbox/example/dart-native/vectorsearch_cities/pubspec.yaml "${dependencyHigherExpr}" update objectbox/example/flutter/event_management_tutorial/event_manager/pubspec.yaml "${dependencyHigherExpr}" update objectbox/example/flutter/event_management_tutorial/many_to_many/pubspec.yaml "${dependencyHigherExpr}" update objectbox/example/flutter/objectbox_demo/pubspec.yaml "${dependencyHigherExpr}"