|
243 | 243 | "text/markdown": [ |
244 | 244 | "---\n", |
245 | 245 | "\n", |
| 246 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L79){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 247 | + "\n", |
246 | 248 | "### QueryBuilder.get_create_query\n", |
247 | 249 | "\n", |
248 | 250 | "> QueryBuilder.get_create_query ()\n", |
|
255 | 257 | "text/plain": [ |
256 | 258 | "---\n", |
257 | 259 | "\n", |
| 260 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L79){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 261 | + "\n", |
258 | 262 | "### QueryBuilder.get_create_query\n", |
259 | 263 | "\n", |
260 | 264 | "> QueryBuilder.get_create_query ()\n", |
|
333 | 337 | " rec = await pool.fetchrow(query)\n", |
334 | 338 | " return rec == None\n", |
335 | 339 | "\n", |
| 340 | + " def _convert_record_meta_to_json(item):\n", |
| 341 | + " if not isinstance(item[1], dict):\n", |
| 342 | + " raise ValueError(\"Cannot mix dictionary and string metadata fields in the same upsert\")\n", |
| 343 | + " return (item[0], json.dumps(item[1]), item[2], item[3])\n", |
| 344 | + "\n", |
| 345 | + "\n", |
336 | 346 | " async def upsert(self, records):\n", |
337 | 347 | " \"\"\"\n", |
338 | 348 | " Performs upsert operation for multiple records.\n", |
|
343 | 353 | " Returns:\n", |
344 | 354 | " None\n", |
345 | 355 | " \"\"\"\n", |
| 356 | + " if isinstance(records[0][1], dict):\n", |
| 357 | + " records = list(map(lambda item: Async._convert_record_meta_to_json(item), records))\n", |
346 | 358 | " query = self.builder.get_upsert_query()\n", |
347 | 359 | " async with await self.connect() as pool:\n", |
348 | 360 | " await pool.executemany(query, records)\n", |
|
422 | 434 | "text/markdown": [ |
423 | 435 | "---\n", |
424 | 436 | "\n", |
| 437 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L229){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 438 | + "\n", |
425 | 439 | "### Async.create_tables\n", |
426 | 440 | "\n", |
427 | 441 | "> Async.create_tables ()\n", |
|
434 | 448 | "text/plain": [ |
435 | 449 | "---\n", |
436 | 450 | "\n", |
| 451 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L229){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 452 | + "\n", |
437 | 453 | "### Async.create_tables\n", |
438 | 454 | "\n", |
439 | 455 | "> Async.create_tables ()\n", |
|
463 | 479 | "text/markdown": [ |
464 | 480 | "---\n", |
465 | 481 | "\n", |
| 482 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L229){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 483 | + "\n", |
466 | 484 | "### Async.create_tables\n", |
467 | 485 | "\n", |
468 | 486 | "> Async.create_tables ()\n", |
|
475 | 493 | "text/plain": [ |
476 | 494 | "---\n", |
477 | 495 | "\n", |
| 496 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L229){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 497 | + "\n", |
478 | 498 | "### Async.create_tables\n", |
479 | 499 | "\n", |
480 | 500 | "> Async.create_tables ()\n", |
|
504 | 524 | "text/markdown": [ |
505 | 525 | "---\n", |
506 | 526 | "\n", |
| 527 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L279){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 528 | + "\n", |
507 | 529 | "### Async.search\n", |
508 | 530 | "\n", |
509 | 531 | "> Async.search (query_embedding:List[float], k:int=10,\n", |
|
517 | 539 | "text/plain": [ |
518 | 540 | "---\n", |
519 | 541 | "\n", |
| 542 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L279){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 543 | + "\n", |
520 | 544 | "### Async.search\n", |
521 | 545 | "\n", |
522 | 546 | "> Async.search (query_embedding:List[float], k:int=10,\n", |
|
566 | 590 | "await vec.create_tables()\n", |
567 | 591 | "empty = await vec.table_is_empty()\n", |
568 | 592 | "assert empty\n", |
569 | | - "await vec.upsert([(uuid.uuid4(), '''{\"key\":\"val\"}''', \"the brown fox\", [1.0,1.2])])\n", |
| 593 | + "await vec.upsert([(uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2])])\n", |
570 | 594 | "empty = await vec.table_is_empty()\n", |
571 | 595 | "assert not empty\n", |
572 | 596 | "\n", |
|
603 | 627 | "rec = await vec.search([1.0, 2.0], filter={\"key_1\":\"val_1\", \"key_2\":\"val_2\"})\n", |
604 | 628 | "assert len(rec) == 1\n", |
605 | 629 | "rec = await vec.search([1.0, 2.0], k=4, filter={\"key_1\":\"val_1\", \"key_2\":\"val_3\"})\n", |
606 | | - "assert len(rec) == 0" |
| 630 | + "assert len(rec) == 0\n", |
| 631 | + "\n", |
| 632 | + "try:\n", |
| 633 | + " # can't upsert using both keys and dictionaries\n", |
| 634 | + " await vec.upsert([ \\\n", |
| 635 | + " (uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2]), \\\n", |
| 636 | + " (uuid.uuid4(), '''{\"key2\":\"val\"}''' , \"the brown fox\", [1.0,1.2])\\\n", |
| 637 | + " ])\n", |
| 638 | + " assert False\n", |
| 639 | + "except ValueError as e:\n", |
| 640 | + " pass\n", |
| 641 | + "\n", |
| 642 | + "try:\n", |
| 643 | + " # can't upsert using both keys and dictionaries opposite order\n", |
| 644 | + " await vec.upsert([ \\\n", |
| 645 | + " (uuid.uuid4(), '''{\"key2\":\"val\"}''', \"the brown fox\", [1.0,1.2]), \\\n", |
| 646 | + " (uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2])\\\n", |
| 647 | + " ])\n", |
| 648 | + " assert False\n", |
| 649 | + "except BaseException as e:\n", |
| 650 | + " pass\n" |
607 | 651 | ] |
608 | 652 | }, |
609 | 653 | { |
|
715 | 759 | " rec = cur.fetchone()\n", |
716 | 760 | " return rec == None\n", |
717 | 761 | "\n", |
| 762 | + " def _convert_record_meta_to_json(item):\n", |
| 763 | + " if not isinstance(item[1], dict):\n", |
| 764 | + " raise ValueError(\"Cannot mix dictionary and string metadata fields in the same upsert\")\n", |
| 765 | + " return (item[0], json.dumps(item[1]), item[2], item[3])\n", |
| 766 | + " \n", |
718 | 767 | " def upsert(self, records):\n", |
719 | 768 | " \"\"\"\n", |
720 | 769 | " Performs upsert operation for multiple records.\n", |
|
725 | 774 | " Returns:\n", |
726 | 775 | " None\n", |
727 | 776 | " \"\"\"\n", |
| 777 | + " if isinstance(records[0][1], dict):\n", |
| 778 | + " records = list(map(lambda item: Async._convert_record_meta_to_json(item), records))\n", |
| 779 | + " \n", |
728 | 780 | " query = self.builder.get_upsert_query()\n", |
729 | 781 | " query, _ = self._translate_to_pyformat(query, None)\n", |
730 | 782 | " with self.connect() as conn:\n", |
|
816 | 868 | "text/markdown": [ |
817 | 869 | "---\n", |
818 | 870 | "\n", |
| 871 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L398){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 872 | + "\n", |
819 | 873 | "### Sync.create_tables\n", |
820 | 874 | "\n", |
821 | 875 | "> Sync.create_tables ()\n", |
|
828 | 882 | "text/plain": [ |
829 | 883 | "---\n", |
830 | 884 | "\n", |
| 885 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L398){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 886 | + "\n", |
831 | 887 | "### Sync.create_tables\n", |
832 | 888 | "\n", |
833 | 889 | "> Sync.create_tables ()\n", |
|
857 | 913 | "text/markdown": [ |
858 | 914 | "---\n", |
859 | 915 | "\n", |
| 916 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L382){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 917 | + "\n", |
860 | 918 | "### Sync.upsert\n", |
861 | 919 | "\n", |
862 | 920 | "> Sync.upsert (records)\n", |
|
872 | 930 | "text/plain": [ |
873 | 931 | "---\n", |
874 | 932 | "\n", |
| 933 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L382){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 934 | + "\n", |
875 | 935 | "### Sync.upsert\n", |
876 | 936 | "\n", |
877 | 937 | "> Sync.upsert (records)\n", |
|
904 | 964 | "text/markdown": [ |
905 | 965 | "---\n", |
906 | 966 | "\n", |
| 967 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L453){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 968 | + "\n", |
907 | 969 | "### Sync.search\n", |
908 | 970 | "\n", |
909 | 971 | "> Sync.search (query_embedding:List[float], k:int=10,\n", |
|
922 | 984 | "text/plain": [ |
923 | 985 | "---\n", |
924 | 986 | "\n", |
| 987 | + "[source](https://github.com/timescale/python-vector/blob/main/timescale_vector/client.py#L453){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", |
| 988 | + "\n", |
925 | 989 | "### Sync.search\n", |
926 | 990 | "\n", |
927 | 991 | "> Sync.search (query_embedding:List[float], k:int=10,\n", |
|
977 | 1041 | "empty = vec.table_is_empty()\n", |
978 | 1042 | "\n", |
979 | 1043 | "assert empty\n", |
980 | | - "vec.upsert([(uuid.uuid4(), '''{\"key\":\"val\"}''', \"the brown fox\", [1.0,1.2])])\n", |
| 1044 | + "vec.upsert([(uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2])])\n", |
981 | 1045 | "empty = vec.table_is_empty()\n", |
982 | 1046 | "assert not empty\n", |
983 | 1047 | "\n", |
|
1016 | 1080 | "rec = vec.search([1.0, 2.0], filter={\"key_1\":\"val_1\", \"key_2\":\"val_2\"})\n", |
1017 | 1081 | "assert len(rec) == 1\n", |
1018 | 1082 | "rec = vec.search([1.0, 2.0], k=4, filter={\"key_1\":\"val_1\", \"key_2\":\"val_3\"})\n", |
1019 | | - "assert len(rec) == 0" |
| 1083 | + "assert len(rec) == 0\n", |
| 1084 | + "\n", |
| 1085 | + "try:\n", |
| 1086 | + " # can't upsert using both keys and dictionaries\n", |
| 1087 | + " await vec.upsert([ \\\n", |
| 1088 | + " (uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2]), \\\n", |
| 1089 | + " (uuid.uuid4(), '''{\"key2\":\"val\"}''' , \"the brown fox\", [1.0,1.2])\\\n", |
| 1090 | + " ])\n", |
| 1091 | + " assert False\n", |
| 1092 | + "except ValueError as e:\n", |
| 1093 | + " pass\n", |
| 1094 | + "\n", |
| 1095 | + "try:\n", |
| 1096 | + " # can't upsert using both keys and dictionaries opposite order\n", |
| 1097 | + " await vec.upsert([ \\\n", |
| 1098 | + " (uuid.uuid4(), '''{\"key2\":\"val\"}''', \"the brown fox\", [1.0,1.2]), \\\n", |
| 1099 | + " (uuid.uuid4(), {\"key\" : \"val\"}, \"the brown fox\", [1.0,1.2])\\\n", |
| 1100 | + " ])\n", |
| 1101 | + " assert False\n", |
| 1102 | + "except BaseException as e:\n", |
| 1103 | + " pass" |
1020 | 1104 | ] |
1021 | 1105 | }, |
1022 | 1106 | { |
|
0 commit comments