@@ -8742,30 +8742,148 @@ describe('Model', function() {
87428742 } ) ;
87438743
87448744 it ( 'createSearchIndexes creates an index for each search index in schema (gh-15465)' , async function ( ) {
8745- const sinon = require ( 'sinon' ) ;
8745+ this . timeout ( 20000 ) ;
8746+ const version = await start . mongodVersion ( ) ;
8747+ if ( version [ 0 ] < 8 || ! process . env . IS_ATLAS ) {
8748+ this . skip ( ) ;
8749+ return ;
8750+ }
87468751 const schema = new mongoose . Schema ( {
87478752 name : String ,
87488753 description : String
87498754 } ) ;
87508755
8751- schema . searchIndex ( { name : 'test' , definition : { mappings : { dynamic : true } } } ) ;
8756+ schema . searchIndex ( {
8757+ name : 'test' ,
8758+ definition : {
8759+ mappings : {
8760+ dynamic : false ,
8761+ fields : { name : { type : 'string' } , description : { type : 'string' } }
8762+ }
8763+ }
8764+ } ) ;
87528765
87538766 const TestModel = db . model ( 'Test' , schema ) ;
87548767
8755- const createSearchIndexStub = sinon . stub ( TestModel , 'createSearchIndex' ) . resolves ( { acknowledged : true } ) ;
8768+ await TestModel . init ( ) ;
8769+ const results = await TestModel . createSearchIndexes ( ) ;
87568770
87578771 try {
8758- const results = await TestModel . createSearchIndexes ( ) ;
8759-
8760- assert . equal ( createSearchIndexStub . callCount , 1 ) ;
87618772 assert . equal ( results . length , 1 ) ;
8762- assert . deepEqual ( results , [ { acknowledged : true } ] ) ;
8773+ assert . deepEqual ( results , [ 'test' ] ) ;
87638774
8764- // Verify that createSearchIndex was called with the correct arguments
8765- assert . ok ( createSearchIndexStub . firstCall . calledWithMatch ( { name : 'test' , definition : { mappings : { dynamic : true } } } ) ) ;
8775+ let indexes = await TestModel . listSearchIndexes ( ) ;
8776+ assert . equal ( indexes . length , 1 ) ;
8777+ assert . equal ( indexes [ 0 ] . name , 'test' ) ;
8778+
8779+ let isQueryable = indexes [ 0 ] . queryable ;
8780+ while ( ! isQueryable ) {
8781+ await delay ( 100 ) ;
8782+ indexes = await TestModel . listSearchIndexes ( ) ;
8783+ isQueryable = indexes [ 0 ] . queryable ;
8784+ }
8785+
8786+ // Insert a document to search.
8787+ await TestModel . create ( { name : 'Atlas Search Example' , description : 'This is a test for MongoDB Atlas Search.' } ) ;
8788+
8789+ // Retry aggregate up to 10 times every 500ms because Lucene index is not immediately queryable
8790+ let searchResults ;
8791+ for ( let tries = 0 ; tries < 10 ; ++ tries ) {
8792+ searchResults = await TestModel . aggregate ( [
8793+ {
8794+ $search : {
8795+ index : 'test' ,
8796+ text : {
8797+ query : 'Atlas' ,
8798+ path : 'name'
8799+ }
8800+ }
8801+ }
8802+ ] ) ;
8803+ if ( searchResults . length > 0 ) {
8804+ break ;
8805+ }
8806+ await delay ( 500 ) ;
8807+ }
8808+ assert . ok ( searchResults . length > 0 ) ;
8809+ assert . strictEqual ( searchResults [ 0 ] . name , 'Atlas Search Example' ) ;
87668810 } finally {
8767- sinon . restore ( ) ;
8811+ await TestModel . dropSearchIndex ( 'test' ) ;
8812+ }
8813+ } ) ;
8814+
8815+ it ( 'can create a vector search index (gh-15465)' , async function ( ) {
8816+ this . timeout ( 10000 ) ;
8817+ const version = await start . mongodVersion ( ) ;
8818+ if ( version [ 0 ] < 8 || ! process . env . IS_ATLAS ) {
8819+ this . skip ( ) ;
8820+ return ;
87688821 }
8822+ const schema = new mongoose . Schema ( {
8823+ name : String ,
8824+ myVector : [ Number ]
8825+ } ) ;
8826+ schema . searchIndex ( {
8827+ name : 'vector_index' ,
8828+ type : 'vectorSearch' ,
8829+ definition : {
8830+ fields : [
8831+ {
8832+ type : 'vector' ,
8833+ numDimensions : 2 ,
8834+ path : 'myVector' ,
8835+ similarity : 'dotProduct' ,
8836+ quantization : 'scalar'
8837+ }
8838+ ]
8839+ }
8840+ } ) ;
8841+
8842+ const TestModel = db . model ( 'Test' , schema ) ;
8843+
8844+ await TestModel . init ( ) ;
8845+ const results = await TestModel . createSearchIndexes ( ) ;
8846+
8847+ assert . equal ( results . length , 1 ) ;
8848+ assert . deepEqual ( results , [ 'vector_index' ] ) ;
8849+
8850+ await TestModel . create ( [ { name : 'Test1' , myVector : [ 0 , 99 ] } , { name : 'Test2' , myVector : [ 99 , 0 ] } ] )
8851+
8852+ let indexes = await TestModel . listSearchIndexes ( ) ;
8853+ let isQueryable = indexes [ 0 ] . queryable ;
8854+ while ( ! isQueryable ) {
8855+ await delay ( 100 ) ;
8856+ indexes = await TestModel . listSearchIndexes ( ) ;
8857+ isQueryable = indexes [ 0 ] . queryable ;
8858+ }
8859+
8860+ let [ doc ] = await TestModel . aggregate ( [
8861+ {
8862+ $vectorSearch : {
8863+ index : 'vector_index' ,
8864+ path : 'myVector' ,
8865+ queryVector : [ 0 , 100 ] ,
8866+ numCandidates : 10 ,
8867+ limit : 1
8868+ }
8869+ }
8870+ ] ) ;
8871+ assert . strictEqual ( doc . name , 'Test1' ) ;
8872+
8873+ [ doc ] = await TestModel . aggregate ( [
8874+ {
8875+ $vectorSearch : {
8876+ index : 'vector_index' ,
8877+ path : 'myVector' ,
8878+ queryVector : [ 100 , 1 ] ,
8879+ numCandidates : 10 ,
8880+ limit : 1
8881+ }
8882+ }
8883+ ] ) ;
8884+ assert . strictEqual ( doc . name , 'Test2' ) ;
8885+
8886+ await TestModel . dropSearchIndex ( 'vector_index' ) ;
87698887 } ) ;
87708888} ) ;
87718889
0 commit comments