Risposta 2 :
Il vero problema è collegare gli elementi del corpo insieme.
Per questo caso abbiamo solo due tipi: muscoli e ossa [qui, raggruppati nella parte del corpo].
Quindi, se iniziamo a sviluppare un gruppo (di ossa), saremo certamente in grado di dettagliarli alla granularità delle ossa.
È ovvio che aggiungere un nuovo gruppo di nervi non sarà difficile se il modello di collegamento tra ossa e muscoli è adeguato.
Sto pensando in Java con OODB per dare esempi.
Uso OpenSource db4objects , è anche Java, possibilità di utilizzare EmbeddedObjectContainer
caricato con API, nessun server, nessun problema di DBA.
Pensa come un disco con utili strumenti di database per gestire I / O complessi come Transparent Activation / Transparent Persistence e altri potenti strumenti come un gestore, ed è in grado di migrare verso un enorme OODB Versant .
Il tuo lavoro: lavora con una classe unica con tre campi:
package ElemBody;
import java.util.HashSet;
import java.util.Set;
public final class ElementBody {
// In true life fields are 'private' with getters and setters
public int typ; // TYP_ELEM.BONES.ordinale() Indexed
public String name; // indexed with UniqueKey
// HashSet (and not SortedSet for optimization) Element linked
public Set<ElementBody> linkedElem = new HashSet<ElementBody>();
// Print utility
@Override
public final String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append(" - ");
for (final ElementBody el : linkedElem) {
sb.append(el.name);
sb.append(", ");
}
sb.append(linkedElem.size());
sb.append(".");
return sb.toString();
}
}
I principali (noiosi) dati di caricamento / collegamento e interrogazione:
package ElemBody;
import java.io.File;
import java.util.Iterator;
import com.db4o.Db4oEmbedded;
import com.db4o.EmbeddedObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.config.EmbeddedConfiguration;
import com.db4o.constraints.UniqueFieldValueConstraint;
import com.db4o.query.Query;
public class PrmBody {
public enum TYP_ELEM {
BONES, MUSCLES, NERVES // here, place for futur types
}
public static void main(final String[] args) {
// one of possible db4o's configuration
final EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
// Managing index and unique key
config.common().objectClass(ElementBody.class).objectField("type")
.indexed(true);
config.common().objectClass(ElementBody.class).objectField("name")
.indexed(true);
config.common().add(
new UniqueFieldValueConstraint(ElementBody.class, "name"));
// You have also an InMemory option, here the file one
// Because of name's uniqueKey option, delete for test, in true live
// read before create/update
new File("Q:/tmp/ElementBody.db4o").delete();
final EmbeddedObjectContainer eoc = Db4oEmbedded.openFile(config,
// "ElementBody.db4o"); // in "user.home" directory
"Q:/tmp/ElementBody.db4o");
// Tedious option to load database.
// Use .properties ou CSV files
// Create BONES
for (final String s : new String[]{"Arms", "Torso Front", "Torso Back",
"LowerBody"}) {
final ElementBody el = new ElementBody();
el.typ = TYP_ELEM.BONES.ordinal();
el.name = s;
eoc.store(el); // save new instance
}
// Create MUSCLES
final String[] muscles = {"Biceps", "Triceps", "Forearms",//
"Abs", "Chest", "Shoulders", //
"Trapezius", "Lats", "Rear Shoulders", "Lower Back", //
"Quads", "Hams", "Hip & Butt", "Calves"};
for (final String s : muscles) {
final ElementBody el = new ElementBody();
el.typ = TYP_ELEM.MUSCLES.ordinal();
el.name = s;
eoc.store(el);
}
// Simplified control of read type form db4o
final Query queryA = eoc.query();
queryA.constrain(ElementBody.class);
queryA.descend("name").constrain("Arms").equal();
final ElementBody arm = (ElementBody) queryA.execute().iterator()
.next();
for (final String s : new String[]{"Biceps", "Triceps", "Forearms",
"Shoulders"}) {
final Query query = eoc.query();
query.constrain(ElementBody.class);
query.descend("name").constrain(s).equal();
final ObjectSet<ElementBody> musT = query.execute();
musT.get(0).linkedElem.add(arm);
arm.linkedElem.add(musT.get(0));
eoc.store(musT.get(0));
}
eoc.store(arm);
final Query queryB = eoc.query();
queryB.constrain(ElementBody.class);
queryB.descend("name").constrain("Torso Front").equal();
final ElementBody tf = (ElementBody) queryB.execute().get(0);
for (final String s : new String[]{"Abs", "Chest", "Shoulders"}) {
final Query query = eoc.query();
query.constrain(ElementBody.class);
query.descend("name").constrain(s).equal();
final ElementBody mus = (ElementBody) query.execute().get(0);
mus.linkedElem.add(tf);
tf.linkedElem.add(mus);
eoc.store(mus);
}
eoc.store(tf);
final Query queryC = eoc.query();
queryC.constrain(ElementBody.class);
queryC.descend("name").constrain("Torso Back").equal();
final ElementBody tb = (ElementBody) queryC.execute().get(0);
for (final String s : new String[]{"Trapezius", "Lats",
"Rear Shoulders", "Lower Back", "Shoulders"}) {
final Query query = eoc.query();
query.constrain(ElementBody.class);
query.descend("name").constrain(s).equal();
final ElementBody mus = (ElementBody) query.execute().get(0);
mus.linkedElem.add(tb);
tb.linkedElem.add(mus);
eoc.store(mus);
}
eoc.store(tb);
eoc.commit(); // End load part // // //
// Two samples of request
final Query r1 = eoc.query();
r1.constrain(ElementBody.class);
r1.descend("typ").constrain(TYP_ELEM.BONES.ordinal()).equal();
for (final Object obj : r1.execute()) {
final ElementBody el = (ElementBody) obj;
System.out.println("\n" + TYP_ELEM.BONES + "\t" + el.name);
final Iterator<ElementBody> it = el.linkedElem.iterator();
while (it.hasNext()) {
System.out.println("\t" + it.next());
}
}
final Query r2 = eoc.query();
r2.constrain(ElementBody.class);
r2.descend("typ").constrain(TYP_ELEM.MUSCLES.ordinal()).equal();
r2.descend("name").constrain("Q").smaller();
r2.descend("name").orderAscending();
final ObjectSet<ElementBody> osEl = r2.execute();
System.out.println("---------------\n" + osEl.size()
+ " muscles in db with A to P prime letter name.");
final Iterator<ElementBody> itEl = osEl.iterator();
int sumLink = 0;
while (itEl.hasNext()) {
final ElementBody elTmp = itEl.next();
System.out.print(elTmp.name + ", ");
sumLink += elTmp.linkedElem.size();
}
System.out.println("\nThose muscles have " + sumLink
+ " links to bones, LowerBody's ones excluded.");
eoc.close();
}
}
Ho aggiunto "Spalle" in due "Torso" per mostrare come puoi alimentare i tuoi link.
Con esempi di query (SODA), sarai in grado di selezionare tutti i gruppi necessari.
Console:
BONES Arms
Forearms - Arms, 1.
Triceps - Arms, 1.
Shoulders - Arms, Torso Back, Torso Front, 3.
Biceps - Arms, 1.
BONES Torso Front
Abs - Torso Front, 1.
Shoulders - Arms, Torso Back, Torso Front, 3.
Chest - Torso Front, 1.
BONES Torso Back
Lower Back - Torso Back, 1.
Trapezius - Torso Back, 1.
Rear Shoulders - Torso Back, 1.
Shoulders - Arms, Torso Back, Torso Front, 3.
Lats - Torso Back, 1.
BONES LowerBody
---------------
9 muscles in db with A to P prime letter name.
Abs, Biceps, Calves, Chest, Forearms, Hams, Hip & Butt, Lats, Lower Back,
Those muscles have 6 links to bones, LowerBody's ones excluded.
Nel mio senso, non è un modello matematico, ma intuitivo:
- qual è la vera domanda? → dove sono gli oggetti reali? (non iniziare con l'astrazione, o la soluzione tecnica, se non è necessario, e decifrare il vero problema, dietro la bella carta dei requisiti)
- chi lavora davvero? → cosa è fatto? (prendi il posto degli oggetti, poi immagina come sei ora rappresentato: ronzio, rappresentazione non così buona no?)
- chi e cosa è realmente necessario (uno sviluppatore pigro vuole verificare / test meno oggetti possibili e oggetti più semplici di uno "tutto fatto in casa")
- gestiamo i dati? → è necessario un database,
- possiamo essere più semplici? → questo richiede tempo, una notte è generalmente un buon tempo trascorso
- è richiesto l'unico problema per l'utente finale? → giusto! guardalo mentre lavora, lui è l'unico uomo in grado di capire quello che vuole, ecco il problema: l'esperienza ti mostrerà come decifrare quelle cose "non dette ma critiche".
Se tutto [o parte] di questo è già stato fatto → usalo
A meno che non sia per uso altamente stress (o OS conosciuto solo da un genio) tutto è già scritto, e spesso ben scritto, ottimizzato e sicuro.
Qui ho usato qualcosa come 'modello di indice inverso interno' (Forse esiste con un altro nome ufficiale):
Il database ha indici sui campi (colonne per SGBDR) come tutti i database che conosci
In OODB aggiungiamo lista / set / BTree / .. per collegare un'istanza di un tipo di oggetto a un'altra dello stesso tipo o ad un'altra istanza di un tipo diverso (ma sempre lo stesso tipo di istanza collegato in una lista).
Se il tuo progetto diventasse più grande e complesso, sarai in grado di utilizzare tali metodi senza difficoltà.
Nessuna complessità per caricare numerosi file CSV, nessuna vera difficoltà per aggiungere query,
- Una classe, tre campi e metodi di base (il tuo lavoro, già fatto, aggiungi solo una query per un oggetto prima di crearlo o aggiornarlo se non vuoi eliminare ogni database per ogni tim - e altri per evitare, ascolta nel documento di riferimento)
- Un OODB (importato) (basta configurarlo, aggiungi TA / TP, puoi inserirlo in Memoria)
- Una classe per il file CSV (import CsvReader)
- Una classe per caricare Csv in DB (Little job, model in PrmBody)
- Alcune classi semplici per query dedicate (non dolorose se si capisce la query SODA)
- Uso JSON, ma prendo lo strumento web preferito per la presentazione (potrebbe essere un mangiatore di tempo per tutti gli usi pubblici).
Sentitevi liberi di dirci se è conveniente per voi.