Megosztás a következőn keresztül:


Relációs SQL-adatok modellezése importáláshoz és indexeléshez az Azure AI Searchben

Az Azure AI Search egy lapos sorkészletet fogad el az indexelési folyamat bemeneteként. Ha a forrásadatok egy SQL Server-relációs adatbázis csatlakoztatott tábláiból származnak, ez a cikk bemutatja, hogyan hozhat létre eredményhalmazt, és hogyan modellezheti a szülő-gyermek kapcsolatot egy Azure AI Search-indexben.

Illusztrációként egy hipotetikus hoteladatbázisra hivatkozunk, amely demoadatokon alapul. Tegyük fel, hogy az adatbázis egy Hotels$ 50 szállodát tartalmazó táblából és egy Rooms$ különböző típusú, díjszabással és felszereltséggel rendelkező táblázatból áll, összesen 750 szoba számára. A táblák között egy-a-többhöz kapcsolat áll fenn. A megközelítésünkben egy nézet 50 sort, szállodánként egy sort ad vissza, és az egyes sorokba beágyazott kapcsolódó helyiségrészleteket tartalmaz.

Táblák és nézet a Hotels adatbázisban

A denormalizált adatok problémája

Az egy-a-többhöz kapcsolatok használatának egyik kihívása, hogy az összekapcsolt táblákra épülő standard lekérdezések denormalizált adatokat adnak vissza, ami nem működik jól az Azure AI Search-forgatókönyvekben. Tekintse meg az alábbi példát, amely a szállodákhoz és szobákhoz csatlakozik.

SELECT * FROM Hotels$
INNER JOIN Rooms$
ON Rooms$.HotelID = Hotels$.HotelID

A lekérdezés eredményei az összes Hotel mezőt, majd az összes Szoba mezőt visszaadják, és az előzetes szállodai adatok ismétlődnek az egyes szobaértékek esetében.

Denormalizált adatok, redundáns szállodaadatok helyiségmezők hozzáadásakor

Bár ez a lekérdezés sikeres a felületen (az összes adat egy egysoros készletben van megadva), nem sikerül a megfelelő dokumentumszerkezetet biztosítani a várt keresési élményhez. Az indexelés során az Azure AI Search minden betöltendő sorhoz létrehoz egy keresési dokumentumot. Ha a keresési dokumentumok úgy néznek ki, mint a fenti eredmények, akkor észlelte volna duplikáltak - hét különálló dokumentumot a Twin Dome hotel egyedül. A "floridai szállodák" lekérdezés hét találatot adna vissza csak a Twin Dome hotelre vonatkozóan, a többi releváns szállodát pedig mélyen a keresési eredményekbe.

A szállodánkénti egy dokumentum várható élményének eléréséhez meg kell adnia egy sorkészletet a megfelelő részletességgel, de teljes információkkal. Ez a cikk bemutatja, hogyan.

Beágyazott JSON-t visszaadó lekérdezés definiálása

A várt keresési élmény biztosításához az adatkészletnek egy sorból kell állnia az Azure AI Search minden egyes keresési dokumentumához. A példánkban minden szállodához egy sort szeretnénk, de azt is szeretnénk, hogy a felhasználók más, számukra fontos helyiségekkel kapcsolatos mezőkre is rákereshessenek, például az éjszakai díjszabásra, az ágyak méretére és számára, vagy a strandra, amelyek mindegyike egy szobarészlet részét képezi.

A megoldás az, hogy beágyazott JSON-ként rögzíti a helyiség részleteit, majd beszúrja a JSON-struktúrát egy nézetben lévő mezőbe, ahogyan a második lépésben látható.

  1. Tegyük fel, hogy két csatlakoztatott táblája van, Hotels$ amelyek Rooms$50 szálloda és 750 szoba adatait tartalmazzák, és a HotelID mezőhöz csatlakoznak. Ezek a táblázatok egyenként 50 szállodát és 750 kapcsolódó szobát tartalmaznak.

    CREATE TABLE [dbo].[Hotels$](
      [HotelID] [nchar](10) NOT NULL,
      [HotelName] [nvarchar](255) NULL,
      [Description] [nvarchar](max) NULL,
      [Description_fr] [nvarchar](max) NULL,
      [Category] [nvarchar](255) NULL,
      [Tags] [nvarchar](255) NULL,
      [ParkingIncluded] [float] NULL,
      [SmokingAllowed] [float] NULL,
      [LastRenovationDate] [smalldatetime] NULL,
      [Rating] [float] NULL,
      [StreetAddress] [nvarchar](255) NULL,
      [City] [nvarchar](255) NULL,
      [State] [nvarchar](255) NULL,
      [ZipCode] [nvarchar](255) NULL,
      [GeoCoordinates] [nvarchar](255) NULL
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
    
    CREATE TABLE [dbo].[Rooms$](
      [HotelID] [nchar](10) NULL,
      [Description] [nvarchar](255) NULL,
      [Description_fr] [nvarchar](255) NULL,
      [Type] [nvarchar](255) NULL,
      [BaseRate] [float] NULL,
      [BedOptions] [nvarchar](255) NULL,
      [SleepsCount] [float] NULL,
      [SmokingAllowed] [float] NULL,
      [Tags] [nvarchar](255) NULL
    ) ON [PRIMARY]
    GO
    
  2. Hozzon létre egy nézetet a szülőtábla (SELECT * from dbo.Hotels$) összes mezőjéből, és adjon hozzá egy új Helyiség mezőt, amely egy beágyazott lekérdezés kimenetét tartalmazza. A FOR JSON AUTO záradék a kimenet JSON-ként való felépítésére SELECT * from dbo.Rooms$ .

    CREATE VIEW [dbo].[HotelRooms]
    AS
    SELECT *, (SELECT *
             FROM dbo.Rooms$
             WHERE dbo.Rooms$.HotelID = dbo.Hotels$.HotelID FOR JSON AUTO) AS Rooms
    FROM dbo.Hotels$
    GO
    

    Az alábbi képernyőképen az eredményül kapott nézet látható, alul a Szobák nvarchar mezővel. A Szobák mező csak a HotelRooms nézetben létezik.

    HotelRooms nézet

  3. Futtassa SELECT * FROM dbo.HotelRooms a sorkészlet lekéréséhez. Ez a lekérdezés 50 sort ad vissza, egy szállodánként, és a hozzá tartozó szobainformációkat JSON-gyűjteményként.

    Sorok a HotelRooms nézetből

Ez a sorkészlet készen áll az Azure AI Searchbe való importálásra.

Feljegyzés

Ez a megközelítés feltételezi, hogy a beágyazott JSON az SQL Server maximális oszlopméretkorlátja alatt van.

Összetett gyűjtemény használata az egy-a-többhöz kapcsolat "több" oldalához

Az Azure AI Search oldalán hozzon létre egy indexsémát, amely beágyazott JSON használatával modellezi az egy-a-többhöz kapcsolatot. Az előző szakaszban létrehozott eredményhalmaz általában a következőben megadott indexsémának felel meg (a rövidség kedvéért kivágunk néhány mezőt).

Az alábbi példa hasonló az összetett adattípusok modellezése című példához. A szobák struktúrája, amely a cikk középpontjában áll, egy hotel nevű index mezőgyűjteményében található. Ez a példa egy összetett címtípust is bemutat, amely abban különbözik a Szobáktól, hogy rögzített elemekből áll, szemben a gyűjteményben engedélyezett elemek többszörös, tetszőleges számával.

{
  "name": "hotels",
  "fields": [
    { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true },
    { "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false },
    { "name": "Description", "type": "Edm.String", "searchable": true, "analyzer": "en.lucene" },
    { "name": "Description_fr", "type": "Edm.String", "searchable": true, "analyzer": "fr.lucene" },
    { "name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "facetable": true },
    { "name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "facetable": true },
    { "name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "facetable": true },
    { "name": "Address", "type": "Edm.ComplexType",
      "fields": [
        { "name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true },
        { "name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true },
        { "name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }
      ]
    },
    { "name": "Rooms", "type": "Collection(Edm.ComplexType)",
      "fields": [
        { "name": "Description", "type": "Edm.String", "searchable": true, "analyzer": "en.lucene" },
        { "name": "Description_fr", "type": "Edm.String", "searchable": true, "analyzer": "fr.lucene" },
        { "name": "Type", "type": "Edm.String", "searchable": true },
        { "name": "BaseRate", "type": "Edm.Double", "filterable": true, "facetable": true },
        { "name": "BedOptions", "type": "Edm.String", "searchable": true, "filterable": true, "facetable": false },
        { "name": "SleepsCount", "type": "Edm.Int32", "filterable": true, "facetable": true },
        { "name": "SmokingAllowed", "type": "Edm.Boolean", "filterable": true, "facetable": false},
        { "name": "Tags", "type": "Edm.Collection", "searchable": true }
      ]
    }
  ]
}

Az előző eredménykészlet és a fenti indexséma alapján a sikeres indexelési művelethez minden szükséges összetevővel rendelkezik. Az összesimított adatkészlet megfelel az indexelési követelményeknek, de megőrzi a részletes információkat. Az Azure AI Search-indexben a keresési eredmények könnyen hotelalapú entitásokba kerülnek, miközben megőrzik az egyes szobák és attribútumaik kontextusát.

Összetett típusú almezők arculati viselkedése

A szülővel rendelkező mezőket, például a Cím és a Szobák alatti mezőket almezőknek nevezzük. Bár hozzárendelhet egy "facetable" attribútumot egy almezőhöz, az aspektusok száma mindig a törzsdokumentumhoz tartozik.

Az olyan összetett típusok esetében, mint a Cím, ahol csak egy "Cím/Város" vagy "Cím/stateProvince" szerepel a dokumentumban, a jellemző viselkedése a várt módon működik. A szobák esetében azonban, ahol az egyes törzsdokumentumokhoz több aldokumentum tartozik, az aspektusok száma félrevezető lehet.

Ahogy a modell összetett típusaiban is említettük: "az eredményben visszaadott dokumentumszámokat a szülődokumentum (szálloda) számítja ki, nem pedig az összetett gyűjtemények (szobák) aldokumentumai. Tegyük fel például, hogy egy szálloda 20 "suite" típusú szobával rendelkezik. Tekintettel a facet=Rooms/Type aspektusparaméterre, a aspektusok száma a szálloda esetében egy, a szobáknál nem 20."

Következő lépések

A saját adatkészletével az Adatok importálása varázslóval hozhatja létre és töltheti be az indexet. A varázsló észleli a beágyazott JSON-gyűjteményt, például a Szobákban található gyűjteményt, és egy összetett típusú gyűjteményt tartalmazó indexsémára következtet.

Az Adatok importálása varázsló által kikövetkesedő index

Az Adatok importálása varázsló alapvető lépéseit az alábbi rövid útmutatóban ismerheti meg.