[Elasticsearch] Mapping van twee indexes

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:56
Situatie
Stel je een game en een game medium voor:

Het spel heeft een titel en kan meerdere genres hebben, bijvoorbeeld "Dragon Ball Karakot" met "Fighting" en "Adventure" als genres

Dan is er een gebruiker die dit spel bezit. De gebruiker is eigenaar van de game op een schijf (medium) op de PlayStation 5.


Het doel:
Ik wil alle games doorzoeken waarbij de gametitel overeenkomt met "Dragon" en het gamegenre 5 is (d.w.z. Fighting) en waarbij de mediumplatform-ID 2 is (d.w.z. PlayStation 5) en de gebruikers-ID 25 is


De vraag:
Wat is de beste manier om dit te doen aangezien er twee afzonderlijke indexen zijn? Of moet ik één geneste query maken of twee query's uitvoeren? Of zijn er andere oplossingen?


Elasticsearch mappings
Elasticsearch mappings die ik tot nu toe heb verzonnen:

Twee afzondelijke mappings
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Games
"mappings": {
    "properties": {
       "title": {
            "type": "text",
            "index": "true"
        },
        "genres": {
            "type": "integer",
            "index": "true"
        }
    }
}


// Mediums
"mappings": {
    "properties": {
        "game_id": {
            "type": "keyword",
            "index": "true"
        },
        "user_id": {
            "type": "integer",
            "index": "true"
        },
        "platform_id": {
            "type": "integer",
            "index": "true"
        }
    }
}


Consolidated Index mapping:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Games
"mappings": {
    "properties": {
        "title": {
            "type": "text",
            "index": "true"
        },
        "genres": {
            "type": "integer",
            "index": "true"
        },
        "mediums": {
            "type": "nested",
            "properties": {
                "user_id": {
                    "type": "integer",
                    "index": "true"
                },
                "platform_id": {
                    "type": "integer",
                    "index": "true"
                }
            }
        }
    }
}


Merged index mapping
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Mediums
"mappings": {
    "properties": {
        "user_id": {
            "type": "integer",
            "index": "true"
        },
        "platform_id": {
            "type": "integer",
            "index": "true"
        }
        "game_id": {
            "type": "keyword",
            "index": "true"
        },
        "game_title": {
            "type": "text",
            "index": "true"
        },
        "game_genres": {
            "type": "integer",
            "index": "true"
        }
    }
}


Allen hebben zo hun voor en nadelen. Op dit moment gebruik ik de tweede (consolidatie), maar merk dat ik tegen limitaties aanloop. Bijvoorbeeld het verwijderen van een gebruiker is niet het verwijderen van een document maar een Elasticsearch script dat de user id opzoekt in de mediums.

De derde is het makkelijkst om te querieen maar daarvoor is er veel dubbele content omdat elk eigenschap van een game over alle mediums wordt gedupliceerd en als een game wijzigd, moet dit voor alle mediums ge-update worden (en een game wijzigd vaak vanwege bijv. een waardering die hier in dit voorbeeld nog niet wordt meegenomen).

Dus nogmaals de vraag (zie boven) wat een goede manier is om dit soort constructies te mappen voor queries met pagination etc. :)

[ Voor 6% gewijzigd door ZeroXT op 20-07-2024 11:42 ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • rufio64
  • Registratie: Februari 2009
  • Laatst online: 09:02
Ik begrijp wel wat je wil doen, maar eerlijk gezegd is een (MySQL) setup veel geschikter voor het opvragen van data op deze (relationele) manier. Ik denk dat je in die zin de verkeerde tool gebruikt voor wat je probeert te bereiken.

Acties:
  • 0 Henk 'm!

  • TheGhostInc
  • Registratie: November 2000
  • Niet online
ZeroXT schreef op zaterdag 20 juli 2024 @ 11:39:
Het doel:
Ik wil alle games doorzoeken waarbij de gametitel overeenkomt met "Dragon" en het gamegenre 5 is (d.w.z. Fighting) en waarbij de mediumplatform-ID 2 is (d.w.z. PlayStation 5) en de gebruikers-ID 25 is


De vraag:
Wat is de beste manier om dit te doen aangezien er twee afzonderlijke indexen zijn? Of moet ik één geneste query maken of twee query's uitvoeren? Of zijn er andere oplossingen?
Het hangt erg van de omvang af van de data. In jouw voorbeeld zal iemand niet snel 1000+ spellen hebben. Er zijn ook maar een paar platformen.

Dus wat zou het probleem zijn met de data binnentrekken, gefilterd op userId en dan de rest van de filtering cliënt side te doen?
De dataset die je binnenkrijgt is zo klein die kun je prima in elke taal verwerken.

Ik ben het wel eens met @rufio64 dat de data erg relationeel is.
Aan de andere kant merk ik ook dat mensen geneigd zijn alles in de query te willen oplossen, tot in het extreme aan toe. Zeker als dat achter een API zit krijg je enorme zoek API's met tientallen opties.
Zoiets als: ik wil spellen uit 1995, o nee, nu wil ik spellen die ik kocht in 1995. Join op join op join, terwijl de resultset altijd een subset is van de 100 spellen van die gebruiker en in de resultset zit de data keurig platgeslagen.

Ook kun je bepaalde data prima cachen. Of ik. @rufio64 of @ZeroXT het spel heeft, de data van het spel is hetzelfde. En de meeste front ends of API's kunnen prima enkele MB's aan data bufferen/cachen. Sterker nog, meestal is geheugen gebruik helemaal geen ding meer.

Acties:
  • 0 Henk 'm!

  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:56
Bedankt voor jullie antwoorden!

Het klopt dat de data behoorelijk relationeel is. Hetgeen waar ik Elasticsearch voor gebruik is vooral het matchen op de titel van het spel met fuzzyness etc. Hier zit ook een autocomplete bij voor suggesties tijdens het typen.

Ik heb twee voorbeelden gepakt maar in werkelijkheid kan men filteren op:

Medium:
- Platform: playstation, gameboy, etc.
- Type: fysieke medium, download, dlc, etc.
- Region: EUR, PAL, NTFS, etc.
- Language: NL, EN, DE, etc.
- Includes: Box, manual, map, etc.
- Edition: game of the year edition, Black label edition etc,
- Launchers: Steam, GOG, EA/Origin, etc.
- Factory sealed: true/false
- Defects: Box in bad condition, sticker on manual, etc.
- Condition: good, poor, bad, mint etc.

Game:
- Genres: Adventure, Sport, Racing, etc
- Themes: Horror, Party, Erotic, Comedy, etc.
- Game Modes: Single player, split screen, multiplayer, etc.
- Player Perspective: Side view, bird view, FPS, etc

En kunnen zoeken op game titel.

Alle data zit ook in een Mysql database, maar de reden dat dit ook allemaal in Elasticsearch zit is vanwege de paginering.
Ik haal alle game id's op uit Elasticsearch die ik vervolgens gebruik om in Mysql de models erbij te zoeken. Maar de paginering komt uit Elasticsearch.

Daarnaast heb ik zelf al een collectie van 1000+ games en is dat ook het resultaatset welke ik gebruik om te testen voor optimale queries en performance.

[ Voor 5% gewijzigd door ZeroXT op 20-07-2024 15:48 ]