Код: Выделить всё
Dataset datasetRowPerimetres = [...]
return groupBy(datasetRowPerimetres)
.agg(collect_list("nomCommuneMembre").alias("nomCommuneMembre"))
.withColumn("mG", map(new Column("sirenGroupement"), new Column("nomCommuneMembre")))
.drop("nomCommuneMembre");
< /code>
, которая показывает мне карту mg < /code> нравится это: < /p>
siregroupment < /th>
< /th>
/>
200000198
{200000198 -> [Beaumont, Ceyrat, Saint-Genès-Champanelle]}
[*] Ключ карты должен быть заменен еще одним < /li>
И города имена городов их объектами городов. I'm abandoning this and return to separate Datasets having objects without array, set or map. При стоимости их пользователи присоединятся к ним по своим ключам, если это необходимо.
у меня часто возникает проблема для отправки списка или набора объектов детей C
having these ones.
I've tried to solve this problem through a custom user aggregation function (Spark 3.5.6).
I'm starting from an open data source CSV, that contains records for French local authorities completed by the cities that are their members:
Код: Выделить всё
L1, C1
L1, C2
L1, C3
L2, C4
L2, C5
[...]
categoriembresgroupement < /th>
communemembregement < /th>
competencexercees < /th>
densitedemographiquiquebipanceabitansaukarexercees < /th>
densitedemographiquiquiquiquipanciqueBitansaukileCaRceeses. /> etablissementPublicterRitoriAldebassin < /th>
fiscalitefinancement < /th>
fiscalitepropre < /th>
Gestiondeaux < /th>
Interpectomental < /th> /> MembreadherentSyndicatmixte < /th>
naturejuridique < /th>
noMgroupement < /th>
nombredecommunesmmebres < /th>
Organigramme < /th>
< /th>
Organigramme < /th>
< /th>
. /> redevanceEnleVementordersmenageres < /th>
siege < /th>
siren < /th>
TaxeEnleventordersmenageres < /th>
ZoneDemontagne < /th>
zonedemontagn />
Commune < /td>
{97401, {974}, {04}, Les Avirons, 218, 11445, 11663, 219740016} < /td>
{Null, {C1020 -> {C1020 -> {C1020 -> {C1020 -> {C1020 -> {C1020 -> {C1020 -> {C1020 -> {C102016 NULL}, C1505 -> {C1505, false, false, NULL}, [...]
491.7
NULL
{NULL, 4108814, NULL, 9325112, 5216298, FPU, NULL, NULL, NULL, NULL, NULL, NULL}
true
null
false
{ile de la réunion mobilés, 891190, 200045276}
communaute_agglomeration < /td>
CA Civis (Communauté Intercommunale des Villes Solidaires) < /td>
6 < /td>
{m. />185848
false
{{ , NULL, NULL, NULL, 97410,[...] [...]
249740077
true
false
< /tr>
commune < /td>
{97404, {974}, {04}, L'Etang -salé, 211, 14329, 14540, 219740040} < /td>
{null> {null> . {C1020, false, false, null}, c1505 -> {c1505, false, false, null}, [...] < /td>
td>491.7
null < /td>
{null, 4108814, null, 93512, 9, 5212, 9, 9312, 9, 9312, 9312, 9312, 9, 9312, 9, 9, 9312, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5112, 9, 9, 9, 512, 9, 5112, 9, FPU, NULL, NULL, NULL, NULL, NULL, NULL}
true
NULL
false
{SM de Pierrefonds, 356662, 259741007}
communaute_agglomeration < /td>
CA Civis (Communauté Intercommunale des Villes Solidaires) < /td>
6 < /td>
{m. />185848
false
{{ , NULL, NULL, NULL, 97410,[...] [...]
249740077
true
false
commune
{97405, {974}, {04}, Petite-Île, 171, 12920, 13091, 219740057}
{NULL, {C1020 -> {C1020, false, false, null}, c1505 -> {c1505, false, false, null}, [...] < /td>
491.7
null < /td>
{null, 410814, null, 9325112, 5298, 5, null, 4108814, null, 9325112, 5298, 5, 5, 5298, 5, 5298, 5, 5298, 5, 5298, 5, 51629, 5, 5, 516129, 5, 5, 5, 51629, 5, 51629, 5, 5, 529, 51629, 5, 5, 529, 529, 529, 516 298, 516 298, 516129, NULL, NULL, NULL, NULL, NULL}
TRUE
null
false
{saep des hirondelles, 320612, 2001079}
communaute_agglomeration < /td>
CA Civis (Communauté Intercommunale des Villes Solidaires) < /td>
6 < /td>
{m. />185848
false
{{ , NULL, NULL, NULL, 97410,[...] [...]
249740077
true
false
commune
{97414, {974}, {04}, Saint-Louis, 676, 54478, 55154, 219740149}
{NULL, {C1020 -> {C1020, false, false, null}, c1505 -> {c1505, false, false, null}, [...] < /td>
td>491.7
null < /td>
{null, 4108814, null, 93512, 9, 5212, 9, 9312, 9, 9312, 9312, 9312, 9, 9312, 9, 9, 9312, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5112, 9, 9, 9, 512, 9, 5112, 9, FPU, NULL, NULL, NULL, NULL, NULL, NULL} < /td>
true < /td>
null < /td>
false < /td>
{sm d'études et de du Scot du Grand Sud, 320611, 3206, 32011, 3206, 3206, 3206, 3201, 3201, 3206, 3206, 3201, 3201, 3201, 3201, 3206, 3201, 3201, 3201, 3201, 3201, 32011, 32011, 3201, 3201, 3201, 32011, 3201, 3201, 3201, 32011, 32011 259741080} < /td>
communaute_agglomeration < /td>
ca civis (communauté intercommunale des villes solides) < /td>
6 < /td>
{m. Null}
185848
false
{{, null, null, null, 97410, [...] [...]
24740077
24740077 />false
commune
{97416, {974}, {04}, Saint-Pierre, 886, 85254, 86140, 219740164}
{null, {c1020 -> {c1020, false, false, null}, c1505 -> {c1505, false, false, null}, [...] < /td>
td>491.7> nul NULL, 9325112, 5216298, FPU, NULL, NULL, NULL, NULL, NULL, NULL} < /TD>
TRUE < /TD>
NULL < /td>
DESHETS DETOR DETOR DESE DETHERS DETHERS DETHERSE < /td>
Ouest de la réunion dénommé ileva, 542144, 200045342}
communaute_agglomeration
CA Civis (Communauté Intercommunale des Villes Solideres)
6 6 . /> {m., Rdc,, Lorion, 70, David, Null} < /td>
185848 < /td>
false < /td>
{, null, null, null, 97410, [...] [...] < /td>
/> 249740077 < /td>
true < /td>
false < /td>
< /tr>
commune < /td>
{97424, {974}, {04}, {04}, {04}, {04}, {04). 5215, 5260, 219740248/ /> null < /td>
{null, 4108814, null, 9325112, 5216298, FPU, NULL, NULL, NULL, NULL, NULL, NULL} < /TD>
< /td>
nul />false
{ , NULL, }
COMMUNAUTE_AGGLOMERATION
CA CIVIS (Communauté Intercommunale des Villes Solidaires)
6
{M., RDC, , Lorion, 70, David, null}
185848
false
{{, null, null, null, 97410, [...] [...]
2477777
247777
247777 24777 247 />true
false
Код: Выделить всё
communeMembreGroupement
Код: Выделить всё
root
|-- competencesExercees: struct
| |-- competenceConservee: boolean
| |-- competences: map
| | |-- key: string
| | |-- value: struct (valueContainsNull = true)
| | | |-- code: string
| | | |-- deleguee: boolean
| | | |-- interetCommunautaire: boolean
| | | |-- obligatoire: boolean
| |-- nombreDeCompetencesExercees: integer
| |-- syndicatALaCarte: boolean
|-- densiteDemographiqueHabitantsAuKilometreCarre: double
|-- etablissementPublicTerritorialDeBassin: boolean
|-- fiscaliteFinancement: struct
| |-- dgfParHabitant: double
| |-- dotationDeCompensation: integer
| |-- dotationDesGroupementsTouristiques: integer
| |-- dotationGlobale: integer
| |-- dotationIntercommunalite: integer
| |-- modeDeFinancement: string
| |-- obsoleteAutreRedevance: integer
| |-- obsoleteAutreTaxe: integer
| |-- obsoleteDGFBonifiee: integer
| |-- obsoleteDSC: integer
| |-- populationDGF: integer
| |-- potentielFiscal: integer
|-- fiscalitePropre: boolean (nullable = false)
|-- gestionDesEaux: boolean
|-- interdepartemental: boolean
|-- membresGroupement: map
| |-- key: string
| |-- value: struct (valueContainsNull = true)
| | |-- categorieMembresGroupement: string
| | |-- communeMembreGroupement: struct
| | | |-- codeCommune: string
| | | |-- codeDepartementCommune: struct
| | | | |-- id: string
| | | |-- codeRegionCommune: struct
| | | | |-- id: string
| | | |-- nomCommune: string
| | | |-- populationCommuneCompteAPart: integer
| | | |-- populationCommuneMunicipale: integer
| | | |-- populationCommuneTotale: integer
| | | |-- sirenCommune: string
| | |-- membreAdherentSyndicatMixte: struct
| | | |-- nomAdherent: string
| | | |-- populationAdherente: integer
| | | |-- sirenAdherent: string
| | |-- sirenGroupement: string
|-- natureJuridique: string
|-- nomGroupement: string
|-- nombreDeCommunesMmebres: integer
|-- organigramme: struct
| |-- civilite: string
| |-- modeDeRepartitionDesSieges: string
| |-- modeDeRepartitionDesSiegesAutre: string
| |-- nomPresident: string
| |-- nombreDeDelegues: integer
| |-- prenomPresident: string
| |-- representationSubstitution: string
|-- population: integer
|-- redevanceEnlevementOrduresMenageres: boolean
|-- siege: struct
| |-- adresseAdministrative: struct
| | |-- bureauDistributeur: string
| | |-- cedex: string
| | |-- codeCommune: struct
| | | |-- id: string
| | |-- codePaysEtranger: string
| | |-- codePostal: string
| | |-- commentaire: string
| | |-- complementNom: string
| | |-- complementVoie: string
| | |-- libelleCedex: string
| | |-- nom: string
| | |-- nomPaysEtranger: string
| | |-- numeroVoie: string
| | |-- repetitionNumeroDansVoie: string
| | |-- typeVoie: string
| | |-- ville: string
| | |-- voie: string
| |-- adresseSiege: struct
| | |-- bureauDistributeur: string
| | |-- cedex: string
| | |-- codeCommune: struct
| | | |-- id: string
| | |-- codePaysEtranger: string
| | |-- codePostal: string
| | |-- commentaire: string
| | |-- complementNom: string
| | |-- complementVoie: string
| | |-- libelleCedex: string
| | |-- nom: string
| | |-- nomPaysEtranger: string
| | |-- numeroVoie: string
| | |-- repetitionNumeroDansVoie: string
| | |-- typeVoie: string
| | |-- ville: string
| | |-- voie: string
| |-- codeCommune: string
| |-- codeDepartementCommune: struct
| | |-- id: string
| |-- codeRegionCommune: struct
| | |-- id: string
| |-- communeSiege: struct
| | |-- arrondissement: string
| | |-- codeCommune: string
| | |-- codeDepartementCommune: struct
| | | |-- id: string
| | |-- codeRegionCommune: struct
| | | |-- id: string
| | |-- commune: struct
| | | |-- arrondissement: string
| | | |-- codeCanton: string
| | | |-- codeCommune: string
| | | |-- codeCommuneParente: string
| | | |-- codeDepartement: string
| | | |-- codeEPCI: string
| | | |-- codeRegion: string
| | | |-- latitude: double
| | | |-- longitude: double
| | | |-- natureJuridiqueEPCI: string
| | | |-- nomCommune: string
| | | |-- nomDepartement: string
| | | |-- nomEPCI: string
| | | |-- nomMajuscules: string
| | | |-- population: integer
| | | |-- sirenCommune: string
| | | |-- strateCommune: integer
| | | |-- surface: double
| | | |-- typeCommune: string
| | | |-- typeNomEtCharniere: string
| | |-- nomCommune: string
| | |-- populationCommuneCompteAPart: integer
| | |-- populationCommuneMunicipale: integer
| | |-- populationCommuneTotale: integer
| | |-- sirenCommune: string
| |-- dateCreation: date
| |-- dateEffet: date
| |-- email: string
| |-- faxAdministratif: string
| |-- faxSiege: string
| |-- siteInternet: string
| |-- telephoneAdministratif: string
| |-- telephoneSiege: string
|-- siren: string
|-- taxeEnlevementOrduresMenageres: boolean
|-- zoneDeMontagne: boolean
Код: Выделить всё
/**
* Agrégateur de {@link Perimetre} en {@link Groupement}
* @author Marc Le Bihan
*/
public class GroupementAggregator extends Aggregator {
@Serial
private static final long serialVersionUID = 1861686194387336535L;
/**
* Renvoyer une valeur neutre pour cette aggrégation
* @return groupement vide
*/
@Override
public Groupement zero() {
Groupement zero = new Groupement();
zero.setNatureJuridique(NatureJuridiqueGroupement.METROPOLE_LYON);
zero.setMembresGroupement(new MembresGroupement());
return zero;
}
/**
* Combine deux valeurs pour en créer une autre (il est possible qu'elle modifie l'objet {@link Groupement} soumis plutôt que d'en créer un autre.
* @param groupement Groupement à réduire (cumuler dedans)
* @param perimetre Périmètre à considérer
* @return Groupement réduit
*/
@Override
public Groupement reduce(Groupement groupement, Perimetre perimetre) {
// Si le groupement que l'on nous soumet est vide, il s'agit de celui créé par la fonction zero.
// Mais il ne nous intéresse pas, et nous préférons recréer un vrai groupement, une première fois, d'après le périmètre reçu.
Groupement groupementReduit = groupement.getSiren() == null ? new Groupement(perimetre) : new Groupement(groupement);
if (groupementReduit.getMembresGroupement() == null) {
groupementReduit.setMembresGroupement(new MembresGroupement());
}
MembreGroupement membre = new MembreGroupement(perimetre);
groupementReduit.getMembresGroupement().add(membre);
return groupementReduit;
}
/**
* Fusionner deux valeurs intermédiaires
* @param a Premier {@link Groupement}
* @param b Deuxième {@link Groupement}
* @return Groupement déduit
*/
@Override
public Groupement merge(Groupement a, Groupement b) {
// Si l'un des groupements est le zéro, retourner l'autre
if (a.getSiren() == null) {
return b;
}
if (b.getSiren() == null) {
return a;
}
// FIXME : Fait un aggregate ici, mais sans tenir compte d'un group by qu'il faudrait faire avant
a.getMembresGroupement().addAll(b.getMembresGroupement());
return a;
}
/**
* Transformer la sortie après réduction
* @param reduction Contenu réduit
* @return {@link Groupement} final
*/
@Override
public Groupement finish(Groupement reduction) {
// Pas de modification à apporter à l'objet final
return reduction;
}
/**
* Renvoyer l'encodeur du type intermédiaire
* @return Encodeur de {@link Groupement}
*/
@Override
public Encoder bufferEncoder() {
return Encoders.bean(Groupement.class);
}
/**
* Renvoyer l'encodeur du type final
* @return Encodeur de {@link Groupement}
*/
@Override
public Encoder outputEncoder() {
return Encoders.bean(Groupement.class);
}
}
< /code>
И я использую его таким образом: < /p>
public Dataset datasetGroupementsAvecMembres(Dataset datasetPerimetre) {
GroupementAggregator agreggateurGroupement = new GroupementAggregator();
TypedColumn groupements = agreggateurGroupement.toColumn().name("mG");
return datasetPerimetre.select(groupements);
}
Это часто вызывает Zero () Метод агрегатора .
[*] его функция. Управление группы объект, который уменьшается, хорошо заполнен:
[*] mese (...)
zero object one side, each time it is called. Так что это не слияет ничего на самом деле, я думаю. Члены. способ.
, но не идеально. Он создавал объекты, но на самом деле не был набором данных , имея его C детей внутри:
Я заполняю группы , который является LinkedHashset of Groupment by siren (
Код: Выделить всё
String
Код: Выделить всё
public Groupements groupementsAvecMembres(Dataset datasetRowPerimetres, int anneeCOG) {
Dataset datasetPerimetres = this.datasetPerimetre.datasetPerimetres(datasetRowPerimetres, anneeCOG);
Dataset datasetGroupements = datasetGroupementsSansMembres(datasetRowPerimetres, anneeCOG);
Dataset datasetMembresGroupements = this.datasetPerimetre.datasetMembresGroupements(datasetPerimetres);
return super.declinaison(new Groupements(),
datasetGroupements, datasetGroupements.col("siren"), Groupement::getSiren,
datasetMembresGroupements, datasetMembresGroupements.col("siren"), m -> m.getCommuneMembreGroupement().getSirenCommune(),
Groupement::getMembresGroupement);
}
< /code>
с: < /p>
public C declinaison(C ensemble,
Dataset parents, Column columnJoinP, Function obtenirClefDuParent,
Dataset enfants, Column columnJoinE, Function obtenirClefEnfant,
Function obtenirMapEnfants) {
Dataset ds = parents.joinWith(enfants, columnJoinP.equalTo(columnJoinE), "inner");
for(Tuple2 tuple : ds.collectAsList()) {
// Rechercher l'objet parent par KP, et l'ajouter à l'ensemble C, vide, s'il n'existe pas.
P source = tuple._1();
KP clefSourceParent = obtenirClefDuParent.apply(source);
P parent = ensemble.computeIfAbsent(clefSourceParent, clef -> tuple._1());
// Dans cet objet parent P, rechercher la liste des enfants E, indexée par KE, et y ajouter notre instance de E.
Map ensembleEnfants = obtenirMapEnfants.apply(parent);
E nouvelEnfant = tuple._2();
KE clefEnfant = obtenirClefEnfant.apply(nouvelEnfant);
ensembleEnfants.put(clefEnfant, nouvelEnfant);
}
return ensemble;
}
< /code>
И этот тест показывает, что он работает: < /p>
// Parametrized by annotation
String condition = String.format("sirenGroupement = %s", sirenGroupement);
Dataset rowPerimetres = datasetRowPerimetres(annee).where(condition);
Groupements groupements = this.groupementsDataset.groupementsAvecMembres(rowPerimetres, annee);
LOGGER.info("Groupements avec membres :");
assertNotEquals(0, groupements.size(), "Au moins un groupement avec membres aurait dû être trouvé pour " + nom);
LOGGER.info("{}", groupements);
< /code>
показывает: < /p>
Groupements avec membres :
2025-08-08 14:39:40.192 INFO 233869 --- [ main] f.e.a.o.s.d.g.GroupementsITCase :
nom : CA CIVIS (Communauté Intercommunale des Villes Solidaires), siren : 249740077, nature : Communauté d''agglomération,
siège : {commune siège : nom : Saint-Pierre, code commune : 97416, siren : 219740164, département : 974, code région : 04, population totale : 84950, municipale : 84077, comptée à part : 873, arrondissement : 2,
commune : {{Code commune : 97416, Nom : Saint-Pierre, Type : null, EPCI : null (null) - null, Nom en majuscules : null, Code département : null - null, Code région : null, Commune parente (d'arrondissement, déléguée, associée) : null, Type article et charnière : null, SIREN de la commune : 219740164, SIREN de l'intercommunalité dont elle est membre : null, arrondissement : 2, code canton : null, population : 84950 (strate : null), surface (en hectares) : null, longitude: null, latitude : null}} (code commune : {13}), département : 974, code région : 04, date de création : 2002-12-26, date d'effet : 2002-12-31,
adresse du siège : Adresse {nom : null, complément de nom : null, complément de voie : 29 Route de l'Entre-Deux, type de voie : null, numéro dans la voie : null, répétition dans la voie : null, voie : null, code postal : 97410, commune : 97410 SAINT-PIERRE, commentaire : null, code commune: null, bureau distributeur : null, code cedex : null, libellé cedex : null, code pays étranger : null, nom pays étranger : null}, téléphone : , fax siège : null, e-mail : [email protected], site internet : www.civis.re,
adresse administrative : Adresse {nom : null, complément de nom : null, complément de voie : null, type de voie : null, numéro dans la voie : null, répétition dans la voie : null, voie : 29, route de l'Entre-Deux, code postal : 97410, commune : 97410 SAINT-PIERRE, commentaire : null, code commune: null, bureau distributeur : null, code cedex : null, libellé cedex : null, code pays étranger : null, nom pays étranger : null}, téléphone administratif : , fax administratif : null},
population : 183407,
organigramme : {mode de répartition des sièges : RDC, autre mode : null, président(e) : (civilité : M., prénom : Michel, nom : FONTAINE), nombre de délégués : null, représentation/substitution (obsolète après 2024) : 0},
compétences : {nombre de compétences exercées (déclarées) : 43, compétences exercées : {C1533=code : C1533, obligatoire : null, déléguée : null, intérêt communautaire : null, C1510=code : C1510, obligatoire : null, déléguée : null, intérêt communautaire : null, C1532=code : C1532, obligatoire : null, déléguée : null, intérêt communautaire : null, [...]}, syndicat à la carte : null, compétence conservée : false}, nombre de communes du groupement: 6, densité démographique au km²: null, interdépartemental : false, zone de montagne : null, établissement public territorial de bassin : null, gestion des eaux : null,
fiscalité et financement : {Dotation globale : null, dotation de compensation : null, dotation de l'intercommunalité : null, dotation des groupements touristiques : null, population dotation globale de financement : null, DGF par habitant : null, potentiel fiscal : null, DGF bonifiée : 0, DSC : 0, autre taxe : null, autre redevance : null}, ordures ménagères : (redevance false, taxe : true),
membres : {
219740057=siren : 249740077, catégorie membres : Commune, commune membre : {nom : Petite-Île, code commune : 97405, siren : 219740057, département : 974, code région : 04, population totale : 12772, municipale : 12617, comptée à part : 155}, membre adhérent à un syndicat mixte : {nom : SM d'études et de programmation du SCOT du Grand Sud, siren : 259741080, population : 317956},
219740016=siren : 249740077, catégorie membres : Commune, commune membre : {nom : Les Avirons, code commune : 97401, siren : 219740016, département : 974, code région : 04, population totale : 11661, municipale : 11434, comptée à part : 227}, membre adhérent à un syndicat mixte : {nom : Ile De La Réunion Mobilités, siren : 200045276, population : 880875},
219740248=siren : 249740077, catégorie membres : Commune, commune membre : {nom : Cilaos, code commune : 97424, siren : 219740248, département : 974, code région : 04, population totale : 5437, municipale : 5390, comptée à part : 47}, membre adhérent à un syndicat mixte : {nom : SM de Pierrefonds, siren : 259741007, population : 353322},
219740149=siren : 249740077, catégorie membres : Commune, commune membre : {nom : Saint-Louis, code commune : 97414, siren : 219740149, département : 974, code région : 04, population totale : 54557, municipale : 53935, comptée à part : 622}, membre adhérent à un syndicat mixte : {nom : SAEP des Hirondelles, siren : 200101079, population : 317956},
219740040=siren : 249740077, catégorie membres : Commune, commune membre : {nom : L'Étang-Salé, code commune : 97404, siren : 219740040, département : 974, code région : 04, population totale : 14030, municipale : 13836, comptée à part : 194}, membre adhérent à un syndicat mixte : {nom : SM de traitement des déchets des microrégions Sud et Ouest de La Réunion dénommé ILEVA, siren : 200045342, population : 536140},
219740164=siren : 249740077, catégorie membres : Commune, commune membre : {nom : Saint-Pierre, code commune : 97416, siren : 219740164, département : 974, code région : 04, population totale : 84950, municipale : 84077, comptée à part : 873}, membre adhérent à un syndicat mixte : {nom : null, siren : null, population : null}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... where-c-is