github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/migration/v2_to_v3/cmd/remove_dup_doc/main.go (about)

     1  // Recherche et supprime les documents
     2  // en double, pour une même contrainte
     3  // Les autres doublons doivent être géré manuellement.
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"database/sql"
     9  	"flag"
    10  	"fmt"
    11  	"log"
    12  
    13  	"github.com/benoitkugler/goACVE/logs"
    14  	"github.com/benoitkugler/goACVE/server/core/rawdata"
    15  )
    16  
    17  func check(err error) {
    18  	if err != nil {
    19  		log.Fatal(err)
    20  	}
    21  }
    22  
    23  func main() {
    24  	dev := flag.Bool("dev", true, "which DB to use")
    25  	flag.Parse()
    26  
    27  	logsDB := logs.DBProd
    28  	if *dev {
    29  		logsDB = logs.DBDev
    30  	}
    31  
    32  	fmt.Println("Connecting on", logsDB.Host, logsDB.Name)
    33  
    34  	db, err := rawdata.ConnectDB(logsDB)
    35  	check(err)
    36  	defer db.Close()
    37  
    38  	liens, err := rawdata.SelectAllDocumentPersonnes(db)
    39  	check(err)
    40  
    41  	// on cherche les multi documents
    42  	type key struct {
    43  		IdContrainte, IdPersonne int64
    44  	}
    45  
    46  	crible := map[key]rawdata.DocumentPersonnes{}
    47  	for _, lien := range liens {
    48  		keyV := key{IdContrainte: lien.IdContrainte, IdPersonne: lien.IdPersonne}
    49  		crible[keyV] = append(crible[keyV], lien)
    50  	}
    51  
    52  	var docsToSupp rawdata.Ids
    53  	for _, docs := range crible {
    54  		if len(docs) > 1 {
    55  			paquets := searchDoublons(db, docs)
    56  			docsToSupp = append(docsToSupp, paquets.selectDocsToSupp()...)
    57  		}
    58  	}
    59  	fmt.Printf("Found %d doublons \n", len(docsToSupp))
    60  	tx, err := db.Begin()
    61  	check(err)
    62  	_, err = rawdata.DeleteDocumentPersonnesByIdDocuments(tx, docsToSupp...)
    63  	if err != nil {
    64  		err = tx.Rollback()
    65  		log.Fatal(err)
    66  	}
    67  	_, err = rawdata.DeleteDocumentsByIds(tx, docsToSupp...)
    68  	if err != nil {
    69  		err = tx.Rollback()
    70  		log.Fatal(err)
    71  	}
    72  	err = tx.Commit()
    73  	check(err)
    74  	fmt.Println("Deleted.")
    75  }
    76  
    77  // stocke une partitions, non couvrante, d'ids
    78  type doublons []rawdata.Set
    79  
    80  // si idExistant n'est pas encore présent, un nouveau set le contenant est ajouté
    81  func (d *doublons) getById(idExistant int64) rawdata.Set {
    82  	for _, paquet := range *d {
    83  		if paquet.Has(idExistant) {
    84  			return paquet
    85  		}
    86  	}
    87  	// on a pas trouvé l'id
    88  	newPaquet := rawdata.NewSet()
    89  	newPaquet.Add(idExistant)
    90  	*d = append(*d, newPaquet)
    91  	return newPaquet
    92  }
    93  
    94  // sélectionne tous les doublons sauf 1 (par paquet)
    95  func (d doublons) selectDocsToSupp() rawdata.Ids {
    96  	var docsToSupp rawdata.Ids
    97  	for _, paquet := range d {
    98  		// paquet a forcément au moins 2 élements
    99  		docsToSupp = append(docsToSupp, paquet.Keys()[1:]...)
   100  	}
   101  	return docsToSupp
   102  }
   103  
   104  // parmi les documents donnés, charge et compare les contenus
   105  func searchDoublons(db *sql.DB, docs rawdata.DocumentPersonnes) doublons {
   106  	// candidats pour des doublons
   107  	// ont-ils le même contenu ?
   108  	var docToLoad rawdata.Ids
   109  	for _, doc := range docs {
   110  		docToLoad = append(docToLoad, doc.IdDocument)
   111  	}
   112  	contenus, err := rawdata.SelectContenuDocumentsByIdDocuments(db, docToLoad...)
   113  	check(err)
   114  	var paquets doublons
   115  	for i, ci := range contenus {
   116  		for j, cj := range contenus {
   117  			if i == j {
   118  				// ne compare pas à soit même
   119  				continue
   120  			}
   121  			if bytes.Equal(ci.Contenu, cj.Contenu) {
   122  				// on a trouvé un doublon
   123  				// on l'ajoute au paquet i
   124  				paquet := paquets.getById(ci.IdDocument)
   125  				paquet.Add(cj.IdDocument)
   126  			}
   127  		}
   128  	}
   129  	return paquets
   130  }