Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.4k views
in Technique[技术] by (71.8m points)

reactjs - Modelling problem N:M relationships using javascript and dexie

I'm trying to build an m:n relationship with react, dexie and dexie-relationsships.

I have tags and blocks, and each tag can link to many blocks, and each block can link to many tags

You can find the example code here: https://codesandbox.io/s/dexie-relations-lpxg6

import React from "react";
import "./styles.css";
import Dexie from "dexie";
import relationships from "dexie-relationships";

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

f = async () => {
  const tagName = "first";

  Dexie.delete("db");

  const db = new Dexie("db", { addons: [relationships] });
  db.version(1).stores({
    tags: `id++, &name, dateCreated`,
    blocks: `id++, dateCreated, content`,
    relations: `id++, tagID -> tags.id, blockID -> blocks.id, dateLinked`
  });

  db.open().catch(function (err) {
    console.error("Failed to open db: " + (err.stack || err));
  });

  db.on("ready", async function () {
    // on('ready') event will fire when database is open but
    // before any other queued operations start executing.
    // By returning a Promise from this event,
    // the framework will wait until promise completes before
    // resuming any queued database operations.

    await db.tags.add({ id: 1, name: tagName, dateCreated: Date.now() });
    await db.blocks.add({ id: 1, content: "bla bla", dateCreated: Date.now() });
    await db.relations.add({
      tagID: 1,
      blockID: 1,
      dateLinked: Date.now(),
      id: 1
    });

    console.log(`tags: ${JSON.stringify(await db.tags.toArray(), null, 4)}`);
    console.log(
      `blocks: ${JSON.stringify(await db.blocks.toArray(), null, 4)}`
    );
    console.log(
      `relations: ${JSON.stringify(await db.relations.toArray(), null, 4)}`
    );

    const rel = await db.relations.where({ tagID: 1 }).with({ tags: "tags" });
    console.log(`relations joined with tags: ${JSON.stringify(rel, null, 4)}`);
    console.log(`rel.tags should be defined: ${rel.tags}`);
  });
};

f();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you are modeling a many to many relationship, one wacky way to do this is to model the relationship between the entities itself.

So you would have a TagBlockRelation object store. The objects in this store would have two main properties, tag and block. One or the other may be missing, but at least one should be specified.

Next, create two indices. Create one index on tag. Create one index on block.

Then look at your CRUD use cases:

  • To create a new tag unlinked to a block, just insert a new relation with only the tag specified
  • To create a new block unlinked to any tag, just insert a new relation with only the block specified
  • To find all relations involving a particular tag, query the tag index for the tag.
  • To find all relations involving a particular block, query the block index for the block.
  • To update a tag, update all objects in the store that match the tag
  • To update a block, update all objects in the store that match the block
  • To delete a tag, delete all objects in the store that match the tag
  • To delete a block, delete all objects in the store that match the block

It seems awkward to store tags and blocks redundantly. However, if these are small properties (e.g. just basic strings or something like this), this is not a big deal. Such redundancy is a very common thing in NoSQL.

So, to summarize. Basically, get rid of your tags and blocks stores. Keep only the relations store. Redundantly store the props of each tag and block in each of the relations. Use indices on the relations store to efficiently query by tag or block.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...