Salvataggio delle ricerche dell'utente in un database

1

Il mio lavoro consiste nel realizzare un'implementazione per salvare le ricerche collegate a un singolo utente, nonché la possibilità di analizzare questi dati per casi aziendali.

I dati verranno utilizzati per consentire agli utenti di visualizzare la cronologia delle ricerche e per il data mining per ottenere informazioni dettagliate sul comportamento degli utenti

Sarà implementato su un'app per trovare case, la scala sarà un singolo paese ma una possibilità di crescita globale.

Soluzione 1:

Salvataggio della stringa di query, ad es. ?price=20000&rooms=3

Tabella Ricerche

  • Tutte le stringhe di query sono inserite in questa tabella con un vincolo univoco e un ID univoco. Pertanto, ogni volta che viene eseguita la stessa ricerca, questa non verrà più inserita.

Tabella UserSearches

  • Ogni volta che viene eseguita una ricerca, un ID di ricerca viene collegato con un ID utente. E un contatore per quante volte l'utente ha eseguito questa ricerca.

Soluzione 2:

Avere un elenco di colonne in un tblSavedSearch corrispondente ai criteri di ricerca - prezzo / zip / # camere da letto / ecc.

Tabella Ricerche

  • I parametri di ogni ricerca sono divisi in colonne e collegati a un ID utente.

La mia conclusione

Penso che la soluzione 2 sia il caso migliore per analizzare i dati per ottenere una comprensione del comportamento individuale e dell'utente comune. Ma non sono sicuro che sia abbastanza scalabile e se sia il modo migliore.

La soluzione 1 è più scalabile, ma richiederà molta programmazione sull'applicazione stessa per recuperare informazioni utili dai dati.

Ci sono altre opzioni disponibili e come faresti?

Modifica

Soluzione 1

Cerca tabella:

Search ID
Field (e.g. rooms, price, city)
Value (e.g. 2, 20 000, New York) <= numbers saved as String.
Counter 

Tabella UserSearches:

User ID
Search ID
Counter
1. User performs search query
2. Search query is decomposed per field (e.g. rooms: 2, city: New york)
3. For each field
   - If field & value combined are unique: 
        insert search in Searches table
   - Else:
        increment counter of the found field & value combination
4. For each search
   - if search ID doesn’t exist:
        insert UserSearch in UserSearches table.
   - Else:
         increment counter of the UserSearch

Soluzione 2

Cerca tabella:

Search ID
Field (e.g. rooms, price, city)
Value (e.g. 2, 20 000, New York) <= numbers saved as String.

Tabella UserSearches:

User ID
Search ID
1. User performs search query
2. Search query is decomposed per field (e.g. rooms: 2, city: New york)
3. each field with its value is inserted into Searches table.
4. for each inserted search, insert UserSearch with the searchID into UserSearches table.

Con il primo metodo possiamo recuperare facilmente la business logic con i campi contatore, questo ridurrà molto la dimensione delle righe da entrambe le tabelle, ma richiederà più logica all'inserimento.

Con il secondo metodo possiamo recuperare la logica di business con query complesse, le dimensioni delle righe di entrambe le tabelle saranno molto più grandi, ma non c'è un sovraccarico sull'inserimento.

Per quanto riguarda le mie conoscenze con i database, la performance di scrittura è più importante della lettura, quindi penso che la soluzione 2 sia la migliore.

Che ne pensi?

EDIT2

Soluzione 3

Cerca tabella:

Search ID
Field (e.g. rooms, price, city)
Value (e.g. 2, 20 000, New York) <= numbers saved as String.
Date

Tabella UserSearches:

User ID
Search ID
Date

Soluzione 4

Tabella UserSearches:

User ID 
Date
Field1 (e.g. rooms)
Field2 (e.g. priceLow)
Field3 (e.g. priceHigh)
etc.
    
posta Soundwave 08.06.2017 - 12:28
fonte

3 risposte

1

Vorrei andare alla seguente tabella UserSearches:

UserId

Data

Quindi aggiungo una colonna per ogni campo

In questo modo, puoi facilmente SELEZIONARE le colonne che vuoi considerare, quindi raggruppare / sommare i dati.

Un caso aziendale che potresti incontrare: quanti utenti diversi hanno cercato un prezzo superiore a 20000:

SELECT count(UserId) 
FROM (SELECT UserId, SUM(price) 
      FROM UserSearches 
      WHERE price > 20000 
      GROUP BY price)

Mi sembra piuttosto semplice.

Il conteggio non è necessario. Non hai una cronologia se non hai una data associata a ogni ricerca .

La tua colonna Field sarà problematica. La tua tabella dovrebbe farti memorizzare dati normalizzati, non coppie di valori-chiave.

MODIFICA (per rispondere al tuo commento)

Se aggiungi un campo alla tua ricerca, aggiungi una colonna, i dati esistenti avranno NULL per questa colonna. Perderai un po 'di informazioni che sono il "contesto" della tua ricerca (quali campi sono disponibili al momento). Se è rilevante per te mantenere il contesto di ogni ricerca, imposta il valore di default su "N / A" che significa "Non disponibile al momento". Non sembra molto pulito (potrebbe essere necessario escludere spesso il valore "N / D") ma è flessibile.

    
risposta data 08.06.2017 - 14:47
fonte
2

Puoi prendere in considerazione una terza soluzione, con una tabella con:

  1. ID di ricerca (chiave)
  2. Campo (chiave, assumendo che un campo appaia solo una volta per ricerca)
  3. Valore

Quindi puoi avere un'altra tabella con:

  1. ID utente (chiave)
  2. ID di ricerca (chiave)
  3. Cerca contatore (o qualsiasi cosa ti serva)

Con questo modello puoi aggiungere e rimuovere campi alla ricerca con un impatto minimo sul database (la Soluzione 2 implica l'aggiunta di colonne per i nuovi campi).

    
risposta data 08.06.2017 - 13:29
fonte
0

Soluzione 2.

Soluzione 1 è non più scalabile per quanto posso dire, e ha una serie di inconvenienti. Il controllo dei duplicati non è così facile come sembra, dal momento che le coppie chiave-valore potrebbero verificarsi in ordine arbitrario nell'URL codificato. In ogni caso, non dovresti accoppiare il database così strettamente al layout URL usato nel frontend. Inoltre viola la prima forma normale codificando più valori in un singolo campo.

    
risposta data 08.06.2017 - 12:54
fonte

Leggi altre domande sui tag