mirror of
https://github.com/lancedb/lancedb.git
synced 2025-12-27 23:12:58 +00:00
Compare commits
6 Commits
python-v0.
...
python-v0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a15337e03 | ||
|
|
96c66fd087 | ||
|
|
0579303602 | ||
|
|
75edb8756c | ||
|
|
88283110f4 | ||
|
|
b3a637fdeb |
@@ -1,5 +1,5 @@
|
|||||||
[tool.bumpversion]
|
[tool.bumpversion]
|
||||||
current_version = "0.21.1"
|
current_version = "0.21.2-beta.0"
|
||||||
parse = """(?x)
|
parse = """(?x)
|
||||||
(?P<major>0|[1-9]\\d*)\\.
|
(?P<major>0|[1-9]\\d*)\\.
|
||||||
(?P<minor>0|[1-9]\\d*)\\.
|
(?P<minor>0|[1-9]\\d*)\\.
|
||||||
|
|||||||
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -4337,7 +4337,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lancedb"
|
name = "lancedb"
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
@@ -4424,7 +4424,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lancedb-node"
|
name = "lancedb-node"
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-ipc",
|
"arrow-ipc",
|
||||||
@@ -4449,7 +4449,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lancedb-nodejs"
|
name = "lancedb-nodejs"
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-ipc",
|
"arrow-ipc",
|
||||||
@@ -4469,7 +4469,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lancedb-python"
|
name = "lancedb-python"
|
||||||
version = "0.24.1"
|
version = "0.24.2-beta.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow",
|
"arrow",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|||||||
12
docs/package-lock.json
generated
12
docs/package-lock.json
generated
@@ -19,7 +19,7 @@
|
|||||||
},
|
},
|
||||||
"../node": {
|
"../node": {
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.12.0",
|
"version": "0.21.2-beta.0",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64",
|
"x64",
|
||||||
"arm64"
|
"arm64"
|
||||||
@@ -65,11 +65,11 @@
|
|||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@lancedb/vectordb-darwin-arm64": "0.12.0",
|
"@lancedb/vectordb-darwin-arm64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-darwin-x64": "0.12.0",
|
"@lancedb/vectordb-darwin-x64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-arm64-gnu": "0.12.0",
|
"@lancedb/vectordb-linux-arm64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-x64-gnu": "0.12.0",
|
"@lancedb/vectordb-linux-x64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-win32-x64-msvc": "0.12.0"
|
"@lancedb/vectordb-win32-x64-msvc": "0.21.2-beta.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@apache-arrow/ts": "^14.0.2",
|
"@apache-arrow/ts": "^14.0.2",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
# SQL Querying
|
||||||
|
|
||||||
You can use DuckDB and Apache Datafusion to query your LanceDB tables using SQL.
|
You can use DuckDB and Apache Datafusion to query your LanceDB tables using SQL.
|
||||||
This guide will show how to query Lance tables them using both.
|
This guide will show how to query Lance tables them using both.
|
||||||
|
|
||||||
We will re-use the dataset [created previously](./pandas_and_pyarrow.md):
|
We will re-use the dataset [created previously](./tables.md):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import lancedb
|
import lancedb
|
||||||
@@ -27,15 +29,10 @@ arrow_table = table.to_lance()
|
|||||||
duckdb.query("SELECT * FROM arrow_table")
|
duckdb.query("SELECT * FROM arrow_table")
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
| vector | item | price |
|
||||||
┌─────────────┬─────────┬────────┐
|
| ----------- | ---- | ----- |
|
||||||
│ vector │ item │ price │
|
| [3.1, 4.1] | foo | 10.0 |
|
||||||
│ float[] │ varchar │ double │
|
| [5.9, 26.5] | bar | 20.0 |
|
||||||
├─────────────┼─────────┼────────┤
|
|
||||||
│ [3.1, 4.1] │ foo │ 10.0 │
|
|
||||||
│ [5.9, 26.5] │ bar │ 20.0 │
|
|
||||||
└─────────────┴─────────┴────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Querying a LanceDB Table with Apache Datafusion
|
## Querying a LanceDB Table with Apache Datafusion
|
||||||
|
|
||||||
@@ -57,12 +54,7 @@ Register the table created with the Datafusion session context.
|
|||||||
--8<-- "python/python/tests/docs/test_guide_tables.py:lance_sql_basic"
|
--8<-- "python/python/tests/docs/test_guide_tables.py:lance_sql_basic"
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
| vector | item | price |
|
||||||
┌─────────────┬─────────┬────────┐
|
| ----------- | ---- | ----- |
|
||||||
│ vector │ item │ price │
|
| [3.1, 4.1] | foo | 10.0 |
|
||||||
│ float[] │ varchar │ double │
|
| [5.9, 26.5] | bar | 20.0 |
|
||||||
├─────────────┼─────────┼────────┤
|
|
||||||
│ [3.1, 4.1] │ foo │ 10.0 │
|
|
||||||
│ [5.9, 26.5] │ bar │ 20.0 │
|
|
||||||
└─────────────┴─────────┴────────┘
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ Creates an instance of MatchQuery.
|
|||||||
- `fuzziness`: The fuzziness level for the query (default is 0).
|
- `fuzziness`: The fuzziness level for the query (default is 0).
|
||||||
- `maxExpansions`: The maximum number of terms to consider for fuzzy matching (default is 50).
|
- `maxExpansions`: The maximum number of terms to consider for fuzzy matching (default is 50).
|
||||||
- `operator`: The logical operator to use for combining terms in the query (default is "OR").
|
- `operator`: The logical operator to use for combining terms in the query (default is "OR").
|
||||||
|
- `prefixLength`: The number of beginning characters being unchanged for fuzzy matching.
|
||||||
|
|
||||||
* **options.boost?**: `number`
|
* **options.boost?**: `number`
|
||||||
|
|
||||||
@@ -50,6 +51,8 @@ Creates an instance of MatchQuery.
|
|||||||
|
|
||||||
* **options.operator?**: [`Operator`](../enumerations/Operator.md)
|
* **options.operator?**: [`Operator`](../enumerations/Operator.md)
|
||||||
|
|
||||||
|
* **options.prefixLength?**: `number`
|
||||||
|
|
||||||
#### Returns
|
#### Returns
|
||||||
|
|
||||||
[`MatchQuery`](MatchQuery.md)
|
[`MatchQuery`](MatchQuery.md)
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ of the given query
|
|||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
* **query**: `string` \| [`IntoVector`](../type-aliases/IntoVector.md) \| [`FullTextQuery`](../interfaces/FullTextQuery.md)
|
* **query**: `string` \| [`IntoVector`](../type-aliases/IntoVector.md) \| [`MultiVector`](../type-aliases/MultiVector.md) \| [`FullTextQuery`](../interfaces/FullTextQuery.md)
|
||||||
the query, a vector or string
|
the query, a vector or string
|
||||||
|
|
||||||
* **queryType?**: `string`
|
* **queryType?**: `string`
|
||||||
@@ -799,7 +799,7 @@ by `query`.
|
|||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
* **vector**: [`IntoVector`](../type-aliases/IntoVector.md)
|
* **vector**: [`IntoVector`](../type-aliases/IntoVector.md) \| [`MultiVector`](../type-aliases/MultiVector.md)
|
||||||
|
|
||||||
#### Returns
|
#### Returns
|
||||||
|
|
||||||
|
|||||||
@@ -386,6 +386,53 @@ called then every valid row from the table will be returned.
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
### maximumNprobes()
|
||||||
|
|
||||||
|
```ts
|
||||||
|
maximumNprobes(maximumNprobes): VectorQuery
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the maximum number of probes used.
|
||||||
|
|
||||||
|
This controls the maximum number of partitions that will be searched. If this
|
||||||
|
number is greater than minimumNprobes then the excess partitions will _only_ be
|
||||||
|
searched if we have not found enough results. This can be useful when there is
|
||||||
|
a narrow filter to allow these queries to spend more time searching and avoid
|
||||||
|
potential false negatives.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
* **maximumNprobes**: `number`
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
[`VectorQuery`](VectorQuery.md)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### minimumNprobes()
|
||||||
|
|
||||||
|
```ts
|
||||||
|
minimumNprobes(minimumNprobes): VectorQuery
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the minimum number of probes used.
|
||||||
|
|
||||||
|
This controls the minimum number of partitions that will be searched. This
|
||||||
|
parameter will impact every query against a vector index, regardless of the
|
||||||
|
filter. See `nprobes` for more details. Higher values will increase recall
|
||||||
|
but will also increase latency.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
* **minimumNprobes**: `number`
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
[`VectorQuery`](VectorQuery.md)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
### nprobes()
|
### nprobes()
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -413,6 +460,10 @@ For best results we recommend tuning this parameter with a benchmark against
|
|||||||
your actual data to find the smallest possible value that will still give
|
your actual data to find the smallest possible value that will still give
|
||||||
you the desired recall.
|
you the desired recall.
|
||||||
|
|
||||||
|
For more fine grained control over behavior when you have a very narrow filter
|
||||||
|
you can use `minimumNprobes` and `maximumNprobes`. This method sets both
|
||||||
|
the minimum and maximum to the same value.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
* **nprobes**: `number`
|
* **nprobes**: `number`
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Enum representing the occurrence of terms in full-text queries.
|
|||||||
|
|
||||||
- `Must`: The term must be present in the document.
|
- `Must`: The term must be present in the document.
|
||||||
- `Should`: The term should contribute to the document score, but is not required.
|
- `Should`: The term should contribute to the document score, but is not required.
|
||||||
|
- `MustNot`: The term must not be present in the document.
|
||||||
|
|
||||||
## Enumeration Members
|
## Enumeration Members
|
||||||
|
|
||||||
@@ -21,6 +22,14 @@ Must: "MUST";
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
### MustNot
|
||||||
|
|
||||||
|
```ts
|
||||||
|
MustNot: "MUST_NOT";
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
### Should
|
### Should
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
- [FieldLike](type-aliases/FieldLike.md)
|
- [FieldLike](type-aliases/FieldLike.md)
|
||||||
- [IntoSql](type-aliases/IntoSql.md)
|
- [IntoSql](type-aliases/IntoSql.md)
|
||||||
- [IntoVector](type-aliases/IntoVector.md)
|
- [IntoVector](type-aliases/IntoVector.md)
|
||||||
|
- [MultiVector](type-aliases/MultiVector.md)
|
||||||
- [RecordBatchLike](type-aliases/RecordBatchLike.md)
|
- [RecordBatchLike](type-aliases/RecordBatchLike.md)
|
||||||
- [SchemaLike](type-aliases/SchemaLike.md)
|
- [SchemaLike](type-aliases/SchemaLike.md)
|
||||||
- [TableLike](type-aliases/TableLike.md)
|
- [TableLike](type-aliases/TableLike.md)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ whether to remove punctuation
|
|||||||
### baseTokenizer?
|
### baseTokenizer?
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
optional baseTokenizer: "raw" | "simple" | "whitespace";
|
optional baseTokenizer: "raw" | "simple" | "whitespace" | "ngram";
|
||||||
```
|
```
|
||||||
|
|
||||||
The tokenizer to use when building the index.
|
The tokenizer to use when building the index.
|
||||||
@@ -71,6 +71,36 @@ tokens longer than this length will be ignored
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
### ngramMaxLength?
|
||||||
|
|
||||||
|
```ts
|
||||||
|
optional ngramMaxLength: number;
|
||||||
|
```
|
||||||
|
|
||||||
|
ngram max length
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### ngramMinLength?
|
||||||
|
|
||||||
|
```ts
|
||||||
|
optional ngramMinLength: number;
|
||||||
|
```
|
||||||
|
|
||||||
|
ngram min length
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### prefixOnly?
|
||||||
|
|
||||||
|
```ts
|
||||||
|
optional prefixOnly: boolean;
|
||||||
|
```
|
||||||
|
|
||||||
|
whether to only index the prefix of the token for ngram tokenizer
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
### removeStopWords?
|
### removeStopWords?
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ The default is 7 days
|
|||||||
// Delete all versions older than 1 day
|
// Delete all versions older than 1 day
|
||||||
const olderThan = new Date();
|
const olderThan = new Date();
|
||||||
olderThan.setDate(olderThan.getDate() - 1));
|
olderThan.setDate(olderThan.getDate() - 1));
|
||||||
tbl.cleanupOlderVersions(olderThan);
|
tbl.optimize({cleanupOlderThan: olderThan});
|
||||||
|
|
||||||
// Delete all versions except the current version
|
// Delete all versions except the current version
|
||||||
tbl.cleanupOlderVersions(new Date());
|
tbl.optimize({cleanupOlderThan: new Date()});
|
||||||
```
|
```
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|||||||
11
docs/src/js/type-aliases/MultiVector.md
Normal file
11
docs/src/js/type-aliases/MultiVector.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
[@lancedb/lancedb](../globals.md) / MultiVector
|
||||||
|
|
||||||
|
# Type Alias: MultiVector
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type MultiVector: IntoVector[];
|
||||||
|
```
|
||||||
@@ -30,7 +30,8 @@ excluded_globs = [
|
|||||||
"../src/rag/advanced_techniques/*.md",
|
"../src/rag/advanced_techniques/*.md",
|
||||||
"../src/guides/scalar_index.md",
|
"../src/guides/scalar_index.md",
|
||||||
"../src/guides/storage.md",
|
"../src/guides/storage.md",
|
||||||
"../src/search.md"
|
"../src/search.md",
|
||||||
|
"../src/guides/sql_querying.md",
|
||||||
]
|
]
|
||||||
|
|
||||||
python_prefix = "py"
|
python_prefix = "py"
|
||||||
|
|||||||
19
java/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
19
java/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
wrapperVersion=3.3.2
|
||||||
|
distributionType=only-script
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
||||||
37
java/README.md
Normal file
37
java/README.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# LanceDB Java SDK
|
||||||
|
|
||||||
|
## Configuration and Initialization
|
||||||
|
|
||||||
|
### LanceDB Cloud
|
||||||
|
|
||||||
|
For LanceDB Cloud, use the simplified builder API:
|
||||||
|
|
||||||
|
```java
|
||||||
|
import com.lancedb.lance.namespace.LanceRestNamespace;
|
||||||
|
|
||||||
|
// If your DB url is db://example-db, then your database here is example-db
|
||||||
|
LanceRestNamespace namespace = LanceDBRestNamespaces.builder()
|
||||||
|
.apiKey("your_lancedb_cloud_api_key")
|
||||||
|
.database("your_database_name")
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### LanceDB Enterprise
|
||||||
|
|
||||||
|
For Enterprise deployments, use your VPC endpoint:
|
||||||
|
|
||||||
|
```java
|
||||||
|
LanceRestNamespace namespace = LanceDBRestNamespaces.builder()
|
||||||
|
.apiKey("your_lancedb_enterprise_api_key")
|
||||||
|
.database("your-top-dir") // Your top level folder under your cloud bucket, e.g. s3://your-bucket/your-top-dir/
|
||||||
|
.hostOverride("http://<vpc_endpoint_dns_name>:80")
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Build:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./mvnw install
|
||||||
|
```
|
||||||
@@ -8,18 +8,24 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.lancedb</groupId>
|
<groupId>com.lancedb</groupId>
|
||||||
<artifactId>lancedb-parent</artifactId>
|
<artifactId>lancedb-parent</artifactId>
|
||||||
<version>0.21.1-final.0</version>
|
<version>0.21.2-beta.0</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>lancedb-core</artifactId>
|
<artifactId>lancedb-core</artifactId>
|
||||||
<name>LanceDB Core</name>
|
<name>${project.artifactId}</name>
|
||||||
|
<description>LanceDB Core</description>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<properties>
|
<properties>
|
||||||
<rust.release.build>false</rust.release.build>
|
<rust.release.build>false</rust.release.build>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lancedb</groupId>
|
||||||
|
<artifactId>lance-namespace-core</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.arrow</groupId>
|
<groupId>org.apache.arrow</groupId>
|
||||||
<artifactId>arrow-vector</artifactId>
|
<artifactId>arrow-vector</artifactId>
|
||||||
|
|||||||
26
java/lance-namespace/pom.xml
Normal file
26
java/lance-namespace/pom.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lancedb</groupId>
|
||||||
|
<artifactId>lancedb-parent</artifactId>
|
||||||
|
<version>0.21.2-beta.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>lancedb-lance-namespace</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>LanceDB Java Integration with Lance Namespace</description>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lancedb</groupId>
|
||||||
|
<artifactId>lance-namespace-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.lancedb.lancedb;
|
||||||
|
|
||||||
|
import com.lancedb.lance.namespace.LanceRestNamespace;
|
||||||
|
import com.lancedb.lance.namespace.client.apache.ApiClient;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/** Util class to help construct a {@link LanceRestNamespace} for LanceDB. */
|
||||||
|
public class LanceDbRestNamespaces {
|
||||||
|
private static final String DEFAULT_REGION = "us-east-1";
|
||||||
|
private static final String CLOUD_URL_PATTERN = "https://%s.%s.api.lancedb.com";
|
||||||
|
|
||||||
|
private String apiKey;
|
||||||
|
private String database;
|
||||||
|
private Optional<String> hostOverride = Optional.empty();
|
||||||
|
private Optional<String> region = Optional.empty();
|
||||||
|
private Map<String, String> additionalConfig = new HashMap<>();
|
||||||
|
|
||||||
|
private LanceDbRestNamespaces() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder instance.
|
||||||
|
*
|
||||||
|
* @return A new LanceRestNamespaceBuilder
|
||||||
|
*/
|
||||||
|
public static LanceDbRestNamespaces builder() {
|
||||||
|
return new LanceDbRestNamespaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the API key (required).
|
||||||
|
*
|
||||||
|
* @param apiKey The LanceDB API key
|
||||||
|
* @return This builder
|
||||||
|
*/
|
||||||
|
public LanceDbRestNamespaces apiKey(String apiKey) {
|
||||||
|
if (apiKey == null || apiKey.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("API key cannot be null or empty");
|
||||||
|
}
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the database name (required).
|
||||||
|
*
|
||||||
|
* @param database The database name
|
||||||
|
* @return This builder
|
||||||
|
*/
|
||||||
|
public LanceDbRestNamespaces database(String database) {
|
||||||
|
if (database == null || database.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Database cannot be null or empty");
|
||||||
|
}
|
||||||
|
this.database = database;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a custom host override (optional). When set, this overrides the default LanceDB Cloud URL
|
||||||
|
* construction. Use this for LanceDB Enterprise deployments.
|
||||||
|
*
|
||||||
|
* @param hostOverride The complete base URL (e.g., "http://your-vpc-endpoint:80")
|
||||||
|
* @return This builder
|
||||||
|
*/
|
||||||
|
public LanceDbRestNamespaces hostOverride(String hostOverride) {
|
||||||
|
this.hostOverride = Optional.ofNullable(hostOverride);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the region for LanceDB Cloud (optional). Defaults to "us-east-1" if not specified. This is
|
||||||
|
* ignored when hostOverride is set.
|
||||||
|
*
|
||||||
|
* @param region The AWS region (e.g., "us-east-1", "eu-west-1")
|
||||||
|
* @return This builder
|
||||||
|
*/
|
||||||
|
public LanceDbRestNamespaces region(String region) {
|
||||||
|
this.region = Optional.ofNullable(region);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add additional configuration parameters.
|
||||||
|
*
|
||||||
|
* @param key The configuration key
|
||||||
|
* @param value The configuration value
|
||||||
|
* @return This builder
|
||||||
|
*/
|
||||||
|
public LanceDbRestNamespaces config(String key, String value) {
|
||||||
|
this.additionalConfig.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the LanceRestNamespace instance.
|
||||||
|
*
|
||||||
|
* @return A configured LanceRestNamespace
|
||||||
|
* @throws IllegalStateException if required parameters are missing
|
||||||
|
*/
|
||||||
|
public LanceRestNamespace build() {
|
||||||
|
// Validate required fields
|
||||||
|
if (apiKey == null) {
|
||||||
|
throw new IllegalStateException("API key is required");
|
||||||
|
}
|
||||||
|
if (database == null) {
|
||||||
|
throw new IllegalStateException("Database is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build configuration map
|
||||||
|
Map<String, String> config = new HashMap<>(additionalConfig);
|
||||||
|
config.put("headers.x-lancedb-database", database);
|
||||||
|
config.put("headers.x-api-key", apiKey);
|
||||||
|
|
||||||
|
// Determine base URL
|
||||||
|
String baseUrl;
|
||||||
|
if (hostOverride.isPresent()) {
|
||||||
|
baseUrl = hostOverride.get();
|
||||||
|
config.put("host_override", hostOverride.get());
|
||||||
|
} else {
|
||||||
|
String effectiveRegion = region.orElse(DEFAULT_REGION);
|
||||||
|
baseUrl = String.format(CLOUD_URL_PATTERN, database, effectiveRegion);
|
||||||
|
config.put("region", effectiveRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and configure ApiClient
|
||||||
|
ApiClient apiClient = new ApiClient();
|
||||||
|
apiClient.setBasePath(baseUrl);
|
||||||
|
|
||||||
|
return new LanceRestNamespace(apiClient, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
259
java/mvnw
vendored
Executable file
259
java/mvnw
vendored
Executable file
@@ -0,0 +1,259 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Apache Maven Wrapper startup batch script, version 3.3.2
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
|
||||||
|
# MVNW_REPOURL - repo url base for downloading maven distribution
|
||||||
|
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||||
|
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set -euf
|
||||||
|
[ "${MVNW_VERBOSE-}" != debug ] || set -x
|
||||||
|
|
||||||
|
# OS specific support.
|
||||||
|
native_path() { printf %s\\n "$1"; }
|
||||||
|
case "$(uname)" in
|
||||||
|
CYGWIN* | MINGW*)
|
||||||
|
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
|
||||||
|
native_path() { cygpath --path --windows "$1"; }
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# set JAVACMD and JAVACCMD
|
||||||
|
set_java_home() {
|
||||||
|
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
|
||||||
|
if [ -n "${JAVA_HOME-}" ]; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
JAVACCMD="$JAVA_HOME/jre/sh/javac"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
JAVACCMD="$JAVA_HOME/bin/javac"
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
|
||||||
|
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
|
||||||
|
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="$(
|
||||||
|
'set' +e
|
||||||
|
'unset' -f command 2>/dev/null
|
||||||
|
'command' -v java
|
||||||
|
)" || :
|
||||||
|
JAVACCMD="$(
|
||||||
|
'set' +e
|
||||||
|
'unset' -f command 2>/dev/null
|
||||||
|
'command' -v javac
|
||||||
|
)" || :
|
||||||
|
|
||||||
|
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
|
||||||
|
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# hash string like Java String::hashCode
|
||||||
|
hash_string() {
|
||||||
|
str="${1:-}" h=0
|
||||||
|
while [ -n "$str" ]; do
|
||||||
|
char="${str%"${str#?}"}"
|
||||||
|
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
|
||||||
|
str="${str#?}"
|
||||||
|
done
|
||||||
|
printf %x\\n $h
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose() { :; }
|
||||||
|
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf %s\\n "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trim() {
|
||||||
|
# MWRAPPER-139:
|
||||||
|
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
|
||||||
|
# Needed for removing poorly interpreted newline sequences when running in more
|
||||||
|
# exotic environments such as mingw bash on Windows.
|
||||||
|
printf "%s" "${1}" | tr -d '[:space:]'
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
|
||||||
|
while IFS="=" read -r key value; do
|
||||||
|
case "${key-}" in
|
||||||
|
distributionUrl) distributionUrl=$(trim "${value-}") ;;
|
||||||
|
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
|
||||||
|
esac
|
||||||
|
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
|
||||||
|
case "${distributionUrl##*/}" in
|
||||||
|
maven-mvnd-*bin.*)
|
||||||
|
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
|
||||||
|
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
|
||||||
|
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
|
||||||
|
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
|
||||||
|
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
|
||||||
|
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
|
||||||
|
*)
|
||||||
|
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
|
||||||
|
distributionPlatform=linux-amd64
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
|
||||||
|
;;
|
||||||
|
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
|
||||||
|
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||||
|
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||||
|
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
|
||||||
|
distributionUrlName="${distributionUrl##*/}"
|
||||||
|
distributionUrlNameMain="${distributionUrlName%.*}"
|
||||||
|
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
|
||||||
|
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
|
||||||
|
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
|
||||||
|
|
||||||
|
exec_maven() {
|
||||||
|
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
|
||||||
|
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -d "$MAVEN_HOME" ]; then
|
||||||
|
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||||
|
exec_maven "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${distributionUrl-}" in
|
||||||
|
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
|
||||||
|
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# prepare tmp dir
|
||||||
|
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
|
||||||
|
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
|
||||||
|
trap clean HUP INT TERM EXIT
|
||||||
|
else
|
||||||
|
die "cannot create temp dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p -- "${MAVEN_HOME%/*}"
|
||||||
|
|
||||||
|
# Download and Install Apache Maven
|
||||||
|
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||||
|
verbose "Downloading from: $distributionUrl"
|
||||||
|
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||||
|
|
||||||
|
# select .zip or .tar.gz
|
||||||
|
if ! command -v unzip >/dev/null; then
|
||||||
|
distributionUrl="${distributionUrl%.zip}.tar.gz"
|
||||||
|
distributionUrlName="${distributionUrl##*/}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# verbose opt
|
||||||
|
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
|
||||||
|
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
|
||||||
|
|
||||||
|
# normalize http auth
|
||||||
|
case "${MVNW_PASSWORD:+has-password}" in
|
||||||
|
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||||
|
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
|
||||||
|
verbose "Found wget ... using wget"
|
||||||
|
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
|
||||||
|
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
|
||||||
|
verbose "Found curl ... using curl"
|
||||||
|
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
|
||||||
|
elif set_java_home; then
|
||||||
|
verbose "Falling back to use Java to download"
|
||||||
|
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
|
||||||
|
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||||
|
cat >"$javaSource" <<-END
|
||||||
|
public class Downloader extends java.net.Authenticator
|
||||||
|
{
|
||||||
|
protected java.net.PasswordAuthentication getPasswordAuthentication()
|
||||||
|
{
|
||||||
|
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
|
||||||
|
}
|
||||||
|
public static void main( String[] args ) throws Exception
|
||||||
|
{
|
||||||
|
setDefault( new Downloader() );
|
||||||
|
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END
|
||||||
|
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
|
||||||
|
verbose " - Compiling Downloader.java ..."
|
||||||
|
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
|
||||||
|
verbose " - Running Downloader.java ..."
|
||||||
|
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||||
|
if [ -n "${distributionSha256Sum-}" ]; then
|
||||||
|
distributionSha256Result=false
|
||||||
|
if [ "$MVN_CMD" = mvnd.sh ]; then
|
||||||
|
echo "Checksum validation is not supported for maven-mvnd." >&2
|
||||||
|
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||||
|
exit 1
|
||||||
|
elif command -v sha256sum >/dev/null; then
|
||||||
|
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
|
||||||
|
distributionSha256Result=true
|
||||||
|
fi
|
||||||
|
elif command -v shasum >/dev/null; then
|
||||||
|
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||||
|
distributionSha256Result=true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||||
|
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ $distributionSha256Result = false ]; then
|
||||||
|
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
|
||||||
|
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# unzip and move
|
||||||
|
if command -v unzip >/dev/null; then
|
||||||
|
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
|
||||||
|
else
|
||||||
|
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
|
||||||
|
fi
|
||||||
|
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
|
||||||
|
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
|
||||||
|
|
||||||
|
clean || :
|
||||||
|
exec_maven "$@"
|
||||||
14
java/pom.xml
14
java/pom.xml
@@ -6,11 +6,10 @@
|
|||||||
|
|
||||||
<groupId>com.lancedb</groupId>
|
<groupId>com.lancedb</groupId>
|
||||||
<artifactId>lancedb-parent</artifactId>
|
<artifactId>lancedb-parent</artifactId>
|
||||||
<version>0.21.1-final.0</version>
|
<version>0.21.2-beta.0</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
<name>LanceDB Parent</name>
|
<description>LanceDB Java SDK Parent POM</description>
|
||||||
<description>LanceDB vector database Java API</description>
|
|
||||||
<url>http://lancedb.com/</url>
|
<url>http://lancedb.com/</url>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
@@ -29,6 +28,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<arrow.version>15.0.0</arrow.version>
|
<arrow.version>15.0.0</arrow.version>
|
||||||
|
<lance-namespace.verison>0.0.1</lance-namespace.verison>
|
||||||
<spotless.skip>false</spotless.skip>
|
<spotless.skip>false</spotless.skip>
|
||||||
<spotless.version>2.30.0</spotless.version>
|
<spotless.version>2.30.0</spotless.version>
|
||||||
<spotless.java.googlejavaformat.version>1.7</spotless.java.googlejavaformat.version>
|
<spotless.java.googlejavaformat.version>1.7</spotless.java.googlejavaformat.version>
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
|
<module>lance-namespace</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
@@ -62,6 +63,11 @@
|
|||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lancedb</groupId>
|
||||||
|
<artifactId>lance-namespace-core</artifactId>
|
||||||
|
<version>${lance-namespace.verison}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.arrow</groupId>
|
<groupId>org.apache.arrow</groupId>
|
||||||
<artifactId>arrow-vector</artifactId>
|
<artifactId>arrow-vector</artifactId>
|
||||||
|
|||||||
44
node/package-lock.json
generated
44
node/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64",
|
"x64",
|
||||||
"arm64"
|
"arm64"
|
||||||
@@ -52,11 +52,11 @@
|
|||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@lancedb/vectordb-darwin-arm64": "0.21.1",
|
"@lancedb/vectordb-darwin-arm64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-darwin-x64": "0.21.1",
|
"@lancedb/vectordb-darwin-x64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-arm64-gnu": "0.21.1",
|
"@lancedb/vectordb-linux-arm64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-x64-gnu": "0.21.1",
|
"@lancedb/vectordb-linux-x64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-win32-x64-msvc": "0.21.1"
|
"@lancedb/vectordb-win32-x64-msvc": "0.21.2-beta.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@apache-arrow/ts": "^14.0.2",
|
"@apache-arrow/ts": "^14.0.2",
|
||||||
@@ -327,9 +327,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@lancedb/vectordb-darwin-arm64": {
|
"node_modules/@lancedb/vectordb-darwin-arm64": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-darwin-arm64/-/vectordb-darwin-arm64-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-darwin-arm64/-/vectordb-darwin-arm64-0.21.2-beta.0.tgz",
|
||||||
"integrity": "sha512-eXeOKgK5s7MSKDzA7Hl4/9E2X8tWWMNV7UJiFdwxrUcop86tM5ePBi8tApRnaQ3wBXrs99XTVBJ7+j+2gzilVA==",
|
"integrity": "sha512-RiYqpKuq9v8A4wFuHt1iPNFYjWJ1KgGFLJwQO4ajp9Hee84sDHq8mP0ATgMcc24hiaOUQ1lRRTULjGbHn4NIYw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -340,9 +340,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@lancedb/vectordb-darwin-x64": {
|
"node_modules/@lancedb/vectordb-darwin-x64": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-darwin-x64/-/vectordb-darwin-x64-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-darwin-x64/-/vectordb-darwin-x64-0.21.2-beta.0.tgz",
|
||||||
"integrity": "sha512-vLoPWfg7OPw5vazLH5/YD/yQkZiTiPniuQgsH+xTodRfLf926lny53G7LQ6nFXNKIzX/jYKtg7AfMU8IcDLSEQ==",
|
"integrity": "sha512-togdP0YIjMYg/hBRMMxW434i5VB789JWU5o3hWrodbX8olEc0Txqw5Dg9CgIOldBIiCti6uTSQiTo6uldZon1w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -353,9 +353,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@lancedb/vectordb-linux-arm64-gnu": {
|
"node_modules/@lancedb/vectordb-linux-arm64-gnu": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-linux-arm64-gnu/-/vectordb-linux-arm64-gnu-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-linux-arm64-gnu/-/vectordb-linux-arm64-gnu-0.21.2-beta.0.tgz",
|
||||||
"integrity": "sha512-IMAxtXj5aHCv9peziN77IxQpkYFj83KvI8zQCHzbMMXv7BspkhAd0PaUViqHqtTf2TUHjYQ66a7clZrEn+xQuQ==",
|
"integrity": "sha512-ErS4IQDQVTYVATPeOj/dZXQR34eZQ5rAXm3vJdQi5K6X4zCDaIjOhpmnwzPBGT9W1idaBAoDJhtNfsFaJ6/PQQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -366,9 +366,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@lancedb/vectordb-linux-x64-gnu": {
|
"node_modules/@lancedb/vectordb-linux-x64-gnu": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-linux-x64-gnu/-/vectordb-linux-x64-gnu-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-linux-x64-gnu/-/vectordb-linux-x64-gnu-0.21.2-beta.0.tgz",
|
||||||
"integrity": "sha512-9oPOxBsYGngIhtC/oC+fQ9V0w9mgFuj2Wyler8f5UYQdiAutsTNyOUA+XjtcROjVZrZ5oUeIrvOQSte9BbpRTg==",
|
"integrity": "sha512-ycDpyBGbfxtnGGa/RQo5+So6dHALiem1pbYc/LDKKluUJpadtXtEwC61o6hZTcejoYjhEE8ET7vA3OCEJfMFaw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -379,9 +379,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@lancedb/vectordb-win32-x64-msvc": {
|
"node_modules/@lancedb/vectordb-win32-x64-msvc": {
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-win32-x64-msvc/-/vectordb-win32-x64-msvc-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@lancedb/vectordb-win32-x64-msvc/-/vectordb-win32-x64-msvc-0.21.2-beta.0.tgz",
|
||||||
"integrity": "sha512-XqDXFLfdjNpDZ5jaqLerdx+sDU4YLuPK3VF4TowwcOlWDrUtI/L1lAyCaKxcyz1qE3VGuZvhNU89N5ioEICb4Q==",
|
"integrity": "sha512-IgVkAP/LiNIQD5P6n/9x3bgQOt5pGJarjtSF8r+ialD95QHmo6tcxrwTy/DlA+H1uI6B6h+sbN0c1KXTh1rYcg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"description": " Serverless, low-latency vector database for AI applications",
|
"description": " Serverless, low-latency vector database for AI applications",
|
||||||
"private": false,
|
"private": false,
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
@@ -89,10 +89,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@lancedb/vectordb-darwin-x64": "0.21.1",
|
"@lancedb/vectordb-darwin-x64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-darwin-arm64": "0.21.1",
|
"@lancedb/vectordb-darwin-arm64": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-x64-gnu": "0.21.1",
|
"@lancedb/vectordb-linux-x64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-linux-arm64-gnu": "0.21.1",
|
"@lancedb/vectordb-linux-arm64-gnu": "0.21.2-beta.0",
|
||||||
"@lancedb/vectordb-win32-x64-msvc": "0.21.1"
|
"@lancedb/vectordb-win32-x64-msvc": "0.21.2-beta.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lancedb-nodejs"
|
name = "lancedb-nodejs"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
description.workspace = true
|
description.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
||||||
|
|
||||||
import { Schema } from "apache-arrow";
|
import { Bool, Field, Int32, List, Schema, Struct, Utf8 } from "apache-arrow";
|
||||||
|
|
||||||
import * as arrow15 from "apache-arrow-15";
|
import * as arrow15 from "apache-arrow-15";
|
||||||
import * as arrow16 from "apache-arrow-16";
|
import * as arrow16 from "apache-arrow-16";
|
||||||
@@ -11,10 +11,12 @@ import * as arrow18 from "apache-arrow-18";
|
|||||||
import {
|
import {
|
||||||
convertToTable,
|
convertToTable,
|
||||||
fromBufferToRecordBatch,
|
fromBufferToRecordBatch,
|
||||||
|
fromDataToBuffer,
|
||||||
fromRecordBatchToBuffer,
|
fromRecordBatchToBuffer,
|
||||||
fromTableToBuffer,
|
fromTableToBuffer,
|
||||||
makeArrowTable,
|
makeArrowTable,
|
||||||
makeEmptyTable,
|
makeEmptyTable,
|
||||||
|
tableFromIPC,
|
||||||
} from "../lancedb/arrow";
|
} from "../lancedb/arrow";
|
||||||
import {
|
import {
|
||||||
EmbeddingFunction,
|
EmbeddingFunction,
|
||||||
@@ -375,8 +377,221 @@ describe.each([arrow15, arrow16, arrow17, arrow18])(
|
|||||||
expect(table2.schema).toEqual(schema);
|
expect(table2.schema).toEqual(schema);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("will handle missing columns in schema alignment when using embeddings", async function () {
|
||||||
|
const schema = new Schema(
|
||||||
|
[
|
||||||
|
new Field("domain", new Utf8(), true),
|
||||||
|
new Field("name", new Utf8(), true),
|
||||||
|
new Field("description", new Utf8(), true),
|
||||||
|
],
|
||||||
|
new Map([["embedding_functions", JSON.stringify([])]]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ domain: "google.com", name: "Google" },
|
||||||
|
{ domain: "facebook.com", name: "Facebook" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const table = await convertToTable(data, undefined, { schema });
|
||||||
|
|
||||||
|
expect(table.numCols).toBe(3);
|
||||||
|
expect(table.numRows).toBe(2);
|
||||||
|
|
||||||
|
const descriptionColumn = table.getChild("description");
|
||||||
|
expect(descriptionColumn).toBeDefined();
|
||||||
|
expect(descriptionColumn?.nullCount).toBe(2);
|
||||||
|
expect(descriptionColumn?.toArray()).toEqual([null, null]);
|
||||||
|
|
||||||
|
expect(table.getChild("domain")?.toArray()).toEqual([
|
||||||
|
"google.com",
|
||||||
|
"facebook.com",
|
||||||
|
]);
|
||||||
|
expect(table.getChild("name")?.toArray()).toEqual([
|
||||||
|
"Google",
|
||||||
|
"Facebook",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will handle completely missing nested struct columns", async function () {
|
||||||
|
const schema = new Schema(
|
||||||
|
[
|
||||||
|
new Field("id", new Utf8(), true),
|
||||||
|
new Field("name", new Utf8(), true),
|
||||||
|
new Field(
|
||||||
|
"metadata",
|
||||||
|
new Struct([
|
||||||
|
new Field("version", new Int32(), true),
|
||||||
|
new Field("author", new Utf8(), true),
|
||||||
|
new Field(
|
||||||
|
"tags",
|
||||||
|
new List(new Field("item", new Utf8(), true)),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
new Map([["embedding_functions", JSON.stringify([])]]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ id: "doc1", name: "Document 1" },
|
||||||
|
{ id: "doc2", name: "Document 2" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const table = await convertToTable(data, undefined, { schema });
|
||||||
|
|
||||||
|
expect(table.numCols).toBe(3);
|
||||||
|
expect(table.numRows).toBe(2);
|
||||||
|
|
||||||
|
const buf = await fromTableToBuffer(table);
|
||||||
|
const retrievedTable = tableFromIPC(buf);
|
||||||
|
|
||||||
|
const rows = [];
|
||||||
|
for (let i = 0; i < retrievedTable.numRows; i++) {
|
||||||
|
rows.push(retrievedTable.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(rows[0].metadata.version).toBe(null);
|
||||||
|
expect(rows[0].metadata.author).toBe(null);
|
||||||
|
expect(rows[0].metadata.tags).toBe(null);
|
||||||
|
expect(rows[0].id).toBe("doc1");
|
||||||
|
expect(rows[0].name).toBe("Document 1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will handle partially missing nested struct fields", async function () {
|
||||||
|
const schema = new Schema(
|
||||||
|
[
|
||||||
|
new Field("id", new Utf8(), true),
|
||||||
|
new Field(
|
||||||
|
"metadata",
|
||||||
|
new Struct([
|
||||||
|
new Field("version", new Int32(), true),
|
||||||
|
new Field("author", new Utf8(), true),
|
||||||
|
new Field("created_at", new Utf8(), true),
|
||||||
|
]),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
new Map([["embedding_functions", JSON.stringify([])]]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ id: "doc1", metadata: { version: 1, author: "Alice" } },
|
||||||
|
{ id: "doc2", metadata: { version: 2 } },
|
||||||
|
];
|
||||||
|
|
||||||
|
const table = await convertToTable(data, undefined, { schema });
|
||||||
|
|
||||||
|
expect(table.numCols).toBe(2);
|
||||||
|
expect(table.numRows).toBe(2);
|
||||||
|
|
||||||
|
const metadataColumn = table.getChild("metadata");
|
||||||
|
expect(metadataColumn).toBeDefined();
|
||||||
|
expect(metadataColumn?.type.toString()).toBe(
|
||||||
|
"Struct<{version:Int32, author:Utf8, created_at:Utf8}>",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will handle multiple levels of nested structures", async function () {
|
||||||
|
const schema = new Schema(
|
||||||
|
[
|
||||||
|
new Field("id", new Utf8(), true),
|
||||||
|
new Field(
|
||||||
|
"config",
|
||||||
|
new Struct([
|
||||||
|
new Field("database", new Utf8(), true),
|
||||||
|
new Field(
|
||||||
|
"connection",
|
||||||
|
new Struct([
|
||||||
|
new Field("host", new Utf8(), true),
|
||||||
|
new Field("port", new Int32(), true),
|
||||||
|
new Field(
|
||||||
|
"ssl",
|
||||||
|
new Struct([
|
||||||
|
new Field("enabled", new Bool(), true),
|
||||||
|
new Field("cert_path", new Utf8(), true),
|
||||||
|
]),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
new Map([["embedding_functions", JSON.stringify([])]]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: "config1",
|
||||||
|
config: {
|
||||||
|
database: "postgres",
|
||||||
|
connection: { host: "localhost" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "config2",
|
||||||
|
config: { database: "mysql" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "config3",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const table = await convertToTable(data, undefined, { schema });
|
||||||
|
|
||||||
|
expect(table.numCols).toBe(2);
|
||||||
|
expect(table.numRows).toBe(3);
|
||||||
|
|
||||||
|
const configColumn = table.getChild("config");
|
||||||
|
expect(configColumn).toBeDefined();
|
||||||
|
expect(configColumn?.type.toString()).toBe(
|
||||||
|
"Struct<{database:Utf8, connection:Struct<{host:Utf8, port:Int32, ssl:Struct<{enabled:Bool, cert_path:Utf8}>}>}>",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will handle missing columns in Arrow table input when using embeddings", async function () {
|
||||||
|
const incompleteTable = makeArrowTable([
|
||||||
|
{ domain: "google.com", name: "Google" },
|
||||||
|
{ domain: "facebook.com", name: "Facebook" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const schema = new Schema(
|
||||||
|
[
|
||||||
|
new Field("domain", new Utf8(), true),
|
||||||
|
new Field("name", new Utf8(), true),
|
||||||
|
new Field("description", new Utf8(), true),
|
||||||
|
],
|
||||||
|
new Map([["embedding_functions", JSON.stringify([])]]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const buf = await fromDataToBuffer(incompleteTable, undefined, schema);
|
||||||
|
|
||||||
|
expect(buf.byteLength).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
const retrievedTable = tableFromIPC(buf);
|
||||||
|
expect(retrievedTable.numCols).toBe(3);
|
||||||
|
expect(retrievedTable.numRows).toBe(2);
|
||||||
|
|
||||||
|
const descriptionColumn = retrievedTable.getChild("description");
|
||||||
|
expect(descriptionColumn).toBeDefined();
|
||||||
|
expect(descriptionColumn?.nullCount).toBe(2);
|
||||||
|
expect(descriptionColumn?.toArray()).toEqual([null, null]);
|
||||||
|
|
||||||
|
expect(retrievedTable.getChild("domain")?.toArray()).toEqual([
|
||||||
|
"google.com",
|
||||||
|
"facebook.com",
|
||||||
|
]);
|
||||||
|
expect(retrievedTable.getChild("name")?.toArray()).toEqual([
|
||||||
|
"Google",
|
||||||
|
"Facebook",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("should correctly retain values in nested struct fields", async function () {
|
it("should correctly retain values in nested struct fields", async function () {
|
||||||
// Define test data with nested struct
|
|
||||||
const testData = [
|
const testData = [
|
||||||
{
|
{
|
||||||
id: "doc1",
|
id: "doc1",
|
||||||
@@ -400,10 +615,8 @@ describe.each([arrow15, arrow16, arrow17, arrow18])(
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Create Arrow table from the data
|
|
||||||
const table = makeArrowTable(testData);
|
const table = makeArrowTable(testData);
|
||||||
|
|
||||||
// Verify schema has the nested struct fields
|
|
||||||
const metadataField = table.schema.fields.find(
|
const metadataField = table.schema.fields.find(
|
||||||
(f) => f.name === "metadata",
|
(f) => f.name === "metadata",
|
||||||
);
|
);
|
||||||
@@ -417,23 +630,17 @@ describe.each([arrow15, arrow16, arrow17, arrow18])(
|
|||||||
"text",
|
"text",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Convert to buffer and back (simulating storage and retrieval)
|
|
||||||
const buf = await fromTableToBuffer(table);
|
const buf = await fromTableToBuffer(table);
|
||||||
const retrievedTable = tableFromIPC(buf);
|
const retrievedTable = tableFromIPC(buf);
|
||||||
|
|
||||||
// Verify the retrieved table has the same structure
|
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (let i = 0; i < retrievedTable.numRows; i++) {
|
for (let i = 0; i < retrievedTable.numRows; i++) {
|
||||||
rows.push(retrievedTable.get(i));
|
rows.push(retrievedTable.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check values in the first row
|
|
||||||
const firstRow = rows[0];
|
const firstRow = rows[0];
|
||||||
expect(firstRow.id).toBe("doc1");
|
expect(firstRow.id).toBe("doc1");
|
||||||
expect(firstRow.vector.toJSON()).toEqual([1, 2, 3]);
|
expect(firstRow.vector.toJSON()).toEqual([1, 2, 3]);
|
||||||
|
|
||||||
// Verify metadata values are preserved (this is where the bug is)
|
|
||||||
expect(firstRow.metadata).toBeDefined();
|
|
||||||
expect(firstRow.metadata.filePath).toBe("/path/to/file1.ts");
|
expect(firstRow.metadata.filePath).toBe("/path/to/file1.ts");
|
||||||
expect(firstRow.metadata.startLine).toBe(10);
|
expect(firstRow.metadata.startLine).toBe(10);
|
||||||
expect(firstRow.metadata.endLine).toBe(20);
|
expect(firstRow.metadata.endLine).toBe(20);
|
||||||
|
|||||||
@@ -1863,4 +1863,43 @@ describe("column name options", () => {
|
|||||||
expect(results[0].query_index).toBe(0);
|
expect(results[0].query_index).toBe(0);
|
||||||
expect(results[1].query_index).toBe(1);
|
expect(results[1].query_index).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("index and search multivectors", async () => {
|
||||||
|
const db = await connect(tmpDir.name);
|
||||||
|
const data = [];
|
||||||
|
// generate 512 random multivectors
|
||||||
|
for (let i = 0; i < 256; i++) {
|
||||||
|
data.push({
|
||||||
|
multivector: Array.from({ length: 10 }, () =>
|
||||||
|
Array(2).fill(Math.random()),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const table = await db.createTable("multivectors", data, {
|
||||||
|
schema: new Schema([
|
||||||
|
new Field(
|
||||||
|
"multivector",
|
||||||
|
new List(
|
||||||
|
new Field(
|
||||||
|
"item",
|
||||||
|
new FixedSizeList(2, new Field("item", new Float32())),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = await table.search(data[0].multivector).limit(10).toArray();
|
||||||
|
expect(results.length).toBe(10);
|
||||||
|
|
||||||
|
await table.createIndex("multivector", {
|
||||||
|
config: Index.ivfPq({ numPartitions: 2, distanceType: "cosine" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const results2 = await table
|
||||||
|
.search(data[0].multivector)
|
||||||
|
.limit(10)
|
||||||
|
.toArray();
|
||||||
|
expect(results2.length).toBe(10);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -107,6 +107,20 @@ export type IntoVector =
|
|||||||
| number[]
|
| number[]
|
||||||
| Promise<Float32Array | Float64Array | number[]>;
|
| Promise<Float32Array | Float64Array | number[]>;
|
||||||
|
|
||||||
|
export type MultiVector = IntoVector[];
|
||||||
|
|
||||||
|
export function isMultiVector(value: unknown): value is MultiVector {
|
||||||
|
return Array.isArray(value) && isIntoVector(value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isIntoVector(value: unknown): value is IntoVector {
|
||||||
|
return (
|
||||||
|
value instanceof Float32Array ||
|
||||||
|
value instanceof Float64Array ||
|
||||||
|
(Array.isArray(value) && !Array.isArray(value[0]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function isArrowTable(value: object): value is TableLike {
|
export function isArrowTable(value: object): value is TableLike {
|
||||||
if (value instanceof ArrowTable) return true;
|
if (value instanceof ArrowTable) return true;
|
||||||
return "schema" in value && "batches" in value;
|
return "schema" in value && "batches" in value;
|
||||||
@@ -839,6 +853,15 @@ async function applyEmbeddingsFromMetadata(
|
|||||||
const vector = makeVector(vectors, destType);
|
const vector = makeVector(vectors, destType);
|
||||||
columns[destColumn] = vector;
|
columns[destColumn] = vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add any missing columns from the schema as null vectors
|
||||||
|
for (const field of schema.fields) {
|
||||||
|
if (!(field.name in columns)) {
|
||||||
|
const nullValues = new Array(table.numRows).fill(null);
|
||||||
|
columns[field.name] = makeVector(nullValues, field.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const newTable = new ArrowTable(columns);
|
const newTable = new ArrowTable(columns);
|
||||||
return alignTable(newTable, schema);
|
return alignTable(newTable, schema);
|
||||||
}
|
}
|
||||||
@@ -987,7 +1010,21 @@ export async function convertToTable(
|
|||||||
embeddings?: EmbeddingFunctionConfig,
|
embeddings?: EmbeddingFunctionConfig,
|
||||||
makeTableOptions?: Partial<MakeArrowTableOptions>,
|
makeTableOptions?: Partial<MakeArrowTableOptions>,
|
||||||
): Promise<ArrowTable> {
|
): Promise<ArrowTable> {
|
||||||
const table = makeArrowTable(data, makeTableOptions);
|
let processedData = data;
|
||||||
|
|
||||||
|
// If we have a schema with embedding metadata, we need to preprocess the data
|
||||||
|
// to ensure all nested fields are present
|
||||||
|
if (
|
||||||
|
makeTableOptions?.schema &&
|
||||||
|
makeTableOptions.schema.metadata?.has("embedding_functions")
|
||||||
|
) {
|
||||||
|
processedData = ensureNestedFieldsExist(
|
||||||
|
data,
|
||||||
|
makeTableOptions.schema as Schema,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const table = makeArrowTable(processedData, makeTableOptions);
|
||||||
return await applyEmbeddings(table, embeddings, makeTableOptions?.schema);
|
return await applyEmbeddings(table, embeddings, makeTableOptions?.schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,7 +1117,16 @@ export async function fromDataToBuffer(
|
|||||||
schema = sanitizeSchema(schema);
|
schema = sanitizeSchema(schema);
|
||||||
}
|
}
|
||||||
if (isArrowTable(data)) {
|
if (isArrowTable(data)) {
|
||||||
return fromTableToBuffer(sanitizeTable(data), embeddings, schema);
|
const table = sanitizeTable(data);
|
||||||
|
// If we have a schema with embedding functions, we need to ensure all columns exist
|
||||||
|
// before applying embeddings, since applyEmbeddingsFromMetadata expects all columns
|
||||||
|
// to be present in the table
|
||||||
|
if (schema && schema.metadata?.has("embedding_functions")) {
|
||||||
|
const alignedTable = alignTableToSchema(table, schema);
|
||||||
|
return fromTableToBuffer(alignedTable, embeddings, schema);
|
||||||
|
} else {
|
||||||
|
return fromTableToBuffer(table, embeddings, schema);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const table = await convertToTable(data, embeddings, { schema });
|
const table = await convertToTable(data, embeddings, { schema });
|
||||||
return fromTableToBuffer(table);
|
return fromTableToBuffer(table);
|
||||||
@@ -1149,7 +1195,7 @@ function alignBatch(batch: RecordBatch, schema: Schema): RecordBatch {
|
|||||||
type: new Struct(schema.fields),
|
type: new Struct(schema.fields),
|
||||||
length: batch.numRows,
|
length: batch.numRows,
|
||||||
nullCount: batch.nullCount,
|
nullCount: batch.nullCount,
|
||||||
children: alignedChildren,
|
children: alignedChildren as unknown as ArrowData<DataType>[],
|
||||||
});
|
});
|
||||||
return new RecordBatch(schema, newData);
|
return new RecordBatch(schema, newData);
|
||||||
}
|
}
|
||||||
@@ -1221,6 +1267,79 @@ function validateSchemaEmbeddings(
|
|||||||
return new Schema(fields, schema.metadata);
|
return new Schema(fields, schema.metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that all nested fields defined in the schema exist in the data,
|
||||||
|
* filling missing fields with null values.
|
||||||
|
*/
|
||||||
|
export function ensureNestedFieldsExist(
|
||||||
|
data: Array<Record<string, unknown>>,
|
||||||
|
schema: Schema,
|
||||||
|
): Array<Record<string, unknown>> {
|
||||||
|
return data.map((row) => {
|
||||||
|
const completeRow: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
for (const field of schema.fields) {
|
||||||
|
if (field.name in row) {
|
||||||
|
if (
|
||||||
|
field.type.constructor.name === "Struct" &&
|
||||||
|
row[field.name] !== null &&
|
||||||
|
row[field.name] !== undefined
|
||||||
|
) {
|
||||||
|
// Handle nested struct
|
||||||
|
const nestedValue = row[field.name] as Record<string, unknown>;
|
||||||
|
completeRow[field.name] = ensureStructFieldsExist(
|
||||||
|
nestedValue,
|
||||||
|
field.type,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Non-struct field or null struct value
|
||||||
|
completeRow[field.name] = row[field.name];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Field is missing from the data - set to null
|
||||||
|
completeRow[field.name] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeRow;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively ensures that all fields in a struct type exist in the data,
|
||||||
|
* filling missing fields with null values.
|
||||||
|
*/
|
||||||
|
function ensureStructFieldsExist(
|
||||||
|
data: Record<string, unknown>,
|
||||||
|
structType: Struct,
|
||||||
|
): Record<string, unknown> {
|
||||||
|
const completeStruct: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
for (const childField of structType.children) {
|
||||||
|
if (childField.name in data) {
|
||||||
|
if (
|
||||||
|
childField.type.constructor.name === "Struct" &&
|
||||||
|
data[childField.name] !== null &&
|
||||||
|
data[childField.name] !== undefined
|
||||||
|
) {
|
||||||
|
// Recursively handle nested struct
|
||||||
|
completeStruct[childField.name] = ensureStructFieldsExist(
|
||||||
|
data[childField.name] as Record<string, unknown>,
|
||||||
|
childField.type,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Non-struct field or null struct value
|
||||||
|
completeStruct[childField.name] = data[childField.name];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Field is missing - set to null
|
||||||
|
completeStruct[childField.name] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeStruct;
|
||||||
|
}
|
||||||
|
|
||||||
interface JsonDataType {
|
interface JsonDataType {
|
||||||
type: string;
|
type: string;
|
||||||
fields?: JsonField[];
|
fields?: JsonField[];
|
||||||
@@ -1354,3 +1473,64 @@ function fieldToJson(field: Field): JsonField {
|
|||||||
metadata: field.metadata,
|
metadata: field.metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function alignTableToSchema(
|
||||||
|
table: ArrowTable,
|
||||||
|
targetSchema: Schema,
|
||||||
|
): ArrowTable {
|
||||||
|
const existingColumns = new Map<string, Vector>();
|
||||||
|
|
||||||
|
// Map existing columns
|
||||||
|
for (const field of table.schema.fields) {
|
||||||
|
existingColumns.set(field.name, table.getChild(field.name)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create vectors for all fields in target schema
|
||||||
|
const alignedColumns: Record<string, Vector> = {};
|
||||||
|
|
||||||
|
for (const field of targetSchema.fields) {
|
||||||
|
if (existingColumns.has(field.name)) {
|
||||||
|
// Column exists, use it
|
||||||
|
alignedColumns[field.name] = existingColumns.get(field.name)!;
|
||||||
|
} else {
|
||||||
|
// Column missing, create null vector
|
||||||
|
alignedColumns[field.name] = createNullVector(field, table.numRows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new table with aligned schema and columns
|
||||||
|
return new ArrowTable(targetSchema, alignedColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNullVector(field: Field, numRows: number): Vector {
|
||||||
|
if (field.type.constructor.name === "Struct") {
|
||||||
|
// For struct types, create a struct with null fields
|
||||||
|
const structType = field.type as Struct;
|
||||||
|
const childVectors = structType.children.map((childField) =>
|
||||||
|
createNullVector(childField, numRows),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create struct data
|
||||||
|
const structData = makeData({
|
||||||
|
type: structType,
|
||||||
|
length: numRows,
|
||||||
|
nullCount: 0,
|
||||||
|
children: childVectors.map((v) => v.data[0]),
|
||||||
|
});
|
||||||
|
|
||||||
|
return arrowMakeVector(structData);
|
||||||
|
} else {
|
||||||
|
// For other types, create a vector of nulls
|
||||||
|
const nullBitmap = new Uint8Array(Math.ceil(numRows / 8));
|
||||||
|
// All bits are 0, meaning all values are null
|
||||||
|
|
||||||
|
const data = makeData({
|
||||||
|
type: field.type,
|
||||||
|
length: numRows,
|
||||||
|
nullCount: numRows,
|
||||||
|
nullBitmap,
|
||||||
|
});
|
||||||
|
|
||||||
|
return arrowMakeVector(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export {
|
|||||||
RecordBatchLike,
|
RecordBatchLike,
|
||||||
DataLike,
|
DataLike,
|
||||||
IntoVector,
|
IntoVector,
|
||||||
|
MultiVector,
|
||||||
} from "./arrow";
|
} from "./arrow";
|
||||||
export { IntoSql, packBits } from "./util";
|
export { IntoSql, packBits } from "./util";
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import {
|
|||||||
Data,
|
Data,
|
||||||
DataType,
|
DataType,
|
||||||
IntoVector,
|
IntoVector,
|
||||||
|
MultiVector,
|
||||||
Schema,
|
Schema,
|
||||||
dataTypeToJson,
|
dataTypeToJson,
|
||||||
fromDataToBuffer,
|
fromDataToBuffer,
|
||||||
|
isMultiVector,
|
||||||
tableFromIPC,
|
tableFromIPC,
|
||||||
} from "./arrow";
|
} from "./arrow";
|
||||||
|
|
||||||
@@ -346,7 +348,7 @@ export abstract class Table {
|
|||||||
* if the query is a string and no embedding function is defined, it will be treated as a full text search query
|
* if the query is a string and no embedding function is defined, it will be treated as a full text search query
|
||||||
*/
|
*/
|
||||||
abstract search(
|
abstract search(
|
||||||
query: string | IntoVector | FullTextQuery,
|
query: string | IntoVector | MultiVector | FullTextQuery,
|
||||||
queryType?: string,
|
queryType?: string,
|
||||||
ftsColumns?: string | string[],
|
ftsColumns?: string | string[],
|
||||||
): VectorQuery | Query;
|
): VectorQuery | Query;
|
||||||
@@ -357,7 +359,7 @@ export abstract class Table {
|
|||||||
* is the same thing as calling `nearestTo` on the builder returned
|
* is the same thing as calling `nearestTo` on the builder returned
|
||||||
* by `query`. @see {@link Query#nearestTo} for more details.
|
* by `query`. @see {@link Query#nearestTo} for more details.
|
||||||
*/
|
*/
|
||||||
abstract vectorSearch(vector: IntoVector): VectorQuery;
|
abstract vectorSearch(vector: IntoVector | MultiVector): VectorQuery;
|
||||||
/**
|
/**
|
||||||
* Add new columns with defined values.
|
* Add new columns with defined values.
|
||||||
* @param {AddColumnsSql[]} newColumnTransforms pairs of column names and
|
* @param {AddColumnsSql[]} newColumnTransforms pairs of column names and
|
||||||
@@ -668,7 +670,7 @@ export class LocalTable extends Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
search(
|
search(
|
||||||
query: string | IntoVector | FullTextQuery,
|
query: string | IntoVector | MultiVector | FullTextQuery,
|
||||||
queryType: string = "auto",
|
queryType: string = "auto",
|
||||||
ftsColumns?: string | string[],
|
ftsColumns?: string | string[],
|
||||||
): VectorQuery | Query {
|
): VectorQuery | Query {
|
||||||
@@ -715,7 +717,15 @@ export class LocalTable extends Table {
|
|||||||
return this.query().nearestTo(queryPromise);
|
return this.query().nearestTo(queryPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
vectorSearch(vector: IntoVector): VectorQuery {
|
vectorSearch(vector: IntoVector | MultiVector): VectorQuery {
|
||||||
|
if (isMultiVector(vector)) {
|
||||||
|
const query = this.query().nearestTo(vector[0]);
|
||||||
|
for (const v of vector.slice(1)) {
|
||||||
|
query.addQueryVector(v);
|
||||||
|
}
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
return this.query().nearestTo(vector);
|
return this.query().nearestTo(vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-darwin-arm64",
|
"name": "@lancedb/lancedb-darwin-arm64",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["darwin"],
|
"os": ["darwin"],
|
||||||
"cpu": ["arm64"],
|
"cpu": ["arm64"],
|
||||||
"main": "lancedb.darwin-arm64.node",
|
"main": "lancedb.darwin-arm64.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-darwin-x64",
|
"name": "@lancedb/lancedb-darwin-x64",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["darwin"],
|
"os": ["darwin"],
|
||||||
"cpu": ["x64"],
|
"cpu": ["x64"],
|
||||||
"main": "lancedb.darwin-x64.node",
|
"main": "lancedb.darwin-x64.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-linux-arm64-gnu",
|
"name": "@lancedb/lancedb-linux-arm64-gnu",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["linux"],
|
"os": ["linux"],
|
||||||
"cpu": ["arm64"],
|
"cpu": ["arm64"],
|
||||||
"main": "lancedb.linux-arm64-gnu.node",
|
"main": "lancedb.linux-arm64-gnu.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-linux-arm64-musl",
|
"name": "@lancedb/lancedb-linux-arm64-musl",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["linux"],
|
"os": ["linux"],
|
||||||
"cpu": ["arm64"],
|
"cpu": ["arm64"],
|
||||||
"main": "lancedb.linux-arm64-musl.node",
|
"main": "lancedb.linux-arm64-musl.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-linux-x64-gnu",
|
"name": "@lancedb/lancedb-linux-x64-gnu",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["linux"],
|
"os": ["linux"],
|
||||||
"cpu": ["x64"],
|
"cpu": ["x64"],
|
||||||
"main": "lancedb.linux-x64-gnu.node",
|
"main": "lancedb.linux-x64-gnu.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-linux-x64-musl",
|
"name": "@lancedb/lancedb-linux-x64-musl",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["linux"],
|
"os": ["linux"],
|
||||||
"cpu": ["x64"],
|
"cpu": ["x64"],
|
||||||
"main": "lancedb.linux-x64-musl.node",
|
"main": "lancedb.linux-x64-musl.node",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-win32-arm64-msvc",
|
"name": "@lancedb/lancedb-win32-arm64-msvc",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb-win32-x64-msvc",
|
"name": "@lancedb/lancedb-win32-x64-msvc",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"os": ["win32"],
|
"os": ["win32"],
|
||||||
"cpu": ["x64"],
|
"cpu": ["x64"],
|
||||||
"main": "lancedb.win32-x64-msvc.node",
|
"main": "lancedb.win32-x64-msvc.node",
|
||||||
|
|||||||
4
nodejs/package-lock.json
generated
4
nodejs/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@lancedb/lancedb",
|
"name": "@lancedb/lancedb",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@lancedb/lancedb",
|
"name": "@lancedb/lancedb",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64",
|
"x64",
|
||||||
"arm64"
|
"arm64"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"ann"
|
"ann"
|
||||||
],
|
],
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "0.21.1",
|
"version": "0.21.2-beta.0",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./dist/index.js",
|
".": "./dist/index.js",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[tool.bumpversion]
|
[tool.bumpversion]
|
||||||
current_version = "0.24.2-beta.0"
|
current_version = "0.24.2-beta.1"
|
||||||
parse = """(?x)
|
parse = """(?x)
|
||||||
(?P<major>0|[1-9]\\d*)\\.
|
(?P<major>0|[1-9]\\d*)\\.
|
||||||
(?P<minor>0|[1-9]\\d*)\\.
|
(?P<minor>0|[1-9]\\d*)\\.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lancedb-python"
|
name = "lancedb-python"
|
||||||
version = "0.24.2-beta.0"
|
version = "0.24.2-beta.1"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
description = "Python bindings for LanceDB"
|
description = "Python bindings for LanceDB"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lancedb-node"
|
name = "lancedb-node"
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
description = "Serverless, low-latency vector database for AI applications"
|
description = "Serverless, low-latency vector database for AI applications"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lancedb"
|
name = "lancedb"
|
||||||
version = "0.21.1"
|
version = "0.21.2-beta.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
description = "LanceDB: A serverless, low-latency vector database for AI applications"
|
description = "LanceDB: A serverless, low-latency vector database for AI applications"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ impl Catalog for ListingCatalog {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the db options to the connect request
|
// Add the db options to the connect request
|
||||||
@@ -243,6 +244,7 @@ impl Catalog for ListingCatalog {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the db options to the connect request
|
// Add the db options to the connect request
|
||||||
@@ -312,6 +314,7 @@ mod tests {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
||||||
@@ -573,6 +576,7 @@ mod tests {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
||||||
@@ -592,6 +596,7 @@ mod tests {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
let catalog = ListingCatalog::connect(&request).await.unwrap();
|
||||||
@@ -608,6 +613,7 @@ mod tests {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
|
session: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = ListingCatalog::connect(&request).await;
|
let result = ListingCatalog::connect(&request).await;
|
||||||
|
|||||||
@@ -627,6 +627,12 @@ pub struct ConnectRequest {
|
|||||||
/// consistency only applies to read operations. Write operations are
|
/// consistency only applies to read operations. Write operations are
|
||||||
/// always consistent.
|
/// always consistent.
|
||||||
pub read_consistency_interval: Option<std::time::Duration>,
|
pub read_consistency_interval: Option<std::time::Duration>,
|
||||||
|
|
||||||
|
/// Optional session for object stores and caching
|
||||||
|
///
|
||||||
|
/// If provided, this session will be used instead of creating a default one.
|
||||||
|
/// This allows for custom configuration of object store registries, caching, etc.
|
||||||
|
pub session: Option<Arc<lance::session::Session>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -645,6 +651,7 @@ impl ConnectBuilder {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
|
session: None,
|
||||||
},
|
},
|
||||||
embedding_registry: None,
|
embedding_registry: None,
|
||||||
}
|
}
|
||||||
@@ -802,6 +809,20 @@ impl ConnectBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a custom session for object stores and caching.
|
||||||
|
///
|
||||||
|
/// By default, a new session with default configuration will be created.
|
||||||
|
/// This method allows you to provide a custom session with your own
|
||||||
|
/// configuration for object store registries, caching, etc.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `session` - A custom session to use for this connection
|
||||||
|
pub fn session(mut self, session: Arc<lance::session::Session>) -> Self {
|
||||||
|
self.request.session = Some(session);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "remote")]
|
#[cfg(feature = "remote")]
|
||||||
fn execute_remote(self) -> Result<Connection> {
|
fn execute_remote(self) -> Result<Connection> {
|
||||||
use crate::remote::db::RemoteDatabaseOptions;
|
use crate::remote::db::RemoteDatabaseOptions;
|
||||||
@@ -884,6 +905,7 @@ impl CatalogConnectBuilder {
|
|||||||
client_config: Default::default(),
|
client_config: Default::default(),
|
||||||
read_consistency_interval: None,
|
read_consistency_interval: None,
|
||||||
options: HashMap::new(),
|
options: HashMap::new(),
|
||||||
|
session: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,6 +265,7 @@ impl ListingDatabase {
|
|||||||
uri,
|
uri,
|
||||||
request.read_consistency_interval,
|
request.read_consistency_interval,
|
||||||
options.new_table_config,
|
options.new_table_config,
|
||||||
|
request.session.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -316,7 +317,10 @@ impl ListingDatabase {
|
|||||||
|
|
||||||
let plain_uri = url.to_string();
|
let plain_uri = url.to_string();
|
||||||
|
|
||||||
let session = Arc::new(lance::session::Session::default());
|
let session = request
|
||||||
|
.session
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| Arc::new(lance::session::Session::default()));
|
||||||
let os_params = ObjectStoreParams {
|
let os_params = ObjectStoreParams {
|
||||||
storage_options: Some(options.storage_options.clone()),
|
storage_options: Some(options.storage_options.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -357,6 +361,7 @@ impl ListingDatabase {
|
|||||||
uri,
|
uri,
|
||||||
request.read_consistency_interval,
|
request.read_consistency_interval,
|
||||||
options.new_table_config,
|
options.new_table_config,
|
||||||
|
request.session.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -367,8 +372,9 @@ impl ListingDatabase {
|
|||||||
path: &str,
|
path: &str,
|
||||||
read_consistency_interval: Option<std::time::Duration>,
|
read_consistency_interval: Option<std::time::Duration>,
|
||||||
new_table_config: NewTableConfig,
|
new_table_config: NewTableConfig,
|
||||||
|
session: Option<Arc<lance::session::Session>>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let session = Arc::new(lance::session::Session::default());
|
let session = session.unwrap_or_else(|| Arc::new(lance::session::Session::default()));
|
||||||
let (object_store, base_path) = ObjectStore::from_uri_and_params(
|
let (object_store, base_path) = ObjectStore::from_uri_and_params(
|
||||||
session.store_registry(),
|
session.store_registry(),
|
||||||
path,
|
path,
|
||||||
|
|||||||
Reference in New Issue
Block a user