Fork me on GitHub
#datascript
<
2017-03-08
>
qqq08:03:09

what is the best way to do "2d geometric" queries in datascript?

qqq08:03:19

so for each item, I have a bbox, which is . (x1, x2, y1, y2)

qqq08:03:30

and I want a query of "get me all items whose bbox interects this given bbox"

tonsky08:03:58

@misha it's also the only way

tonsky08:03:23

Not very efficient though

tonsky08:03:12

Might be better idea to do two d/datoms calls and merge results yourself

tonsky08:03:03

Datomic can actually leverage indexes in queries where predicate is one of < <= > >=

tonsky08:03:40

But Datascript can't yet

linuss11:03:38

Hey guys! I'm using a datascript DB with the following schema:

(def schema
  {:form/id {
             :db/cardinality :db.cardinality/one
             :db/unique :db.unique/identity}
   :form/key {
              :db/cardinality :db.cardinality/one
              :db/unique :db.unique/identity}
   :form/content {
                  :db/valueType :db.type/ref
                  :db/cardinality :db.cardinality/many
                  :db/isComponent true}
   :field/name {
                :db/cardinality :db.cardinality/one}
   :field/label {
                 :db/cardinality :db.cardinality/one}
   :field/type {
                :db/cardinality :db.cardinality/one}
   :field/validations {
                       :db/cardinality :db.cardinality/many}
 })
Now, whenever I add a form (`d/transact! conn [form])` with the same key twice, the form/id gets overwritten just like expected. The form/content however is not overwritten, but appended to (resulting in a form with each field twice). I feel like there should be a nicer way than checking for existence and then retracting the entity manually before re-adding a form...

tonsky11:03:09

form/content references fields, right?

tonsky11:03:35

what’s your definition of field being the same?

linuss11:03:03

Yes. Fields being the same means I transact the exact same datastructure twice

linuss11:03:28

Which ends up in the DB as duplicate fields, linked to the same :form/content

tonsky11:03:44

so you need to compare each and every attribute in a field to decide whether it’s the same or a new one

tonsky11:03:08

there’s nothing for you to help doing that in DataScript

linuss11:03:37

If I wanted to add new fields this way, yes. What I'd like to happen is to have the :form/content refer to a whole new collection of fields once I re-enter a form with the same key

tonsky11:03:48

so you need to drop all old ones and insert new ones, creating new entities from them

tonsky11:03:56

I’m afraid you’d have to do that manually

linuss11:03:18

Okay, too bad, but good to know. Thanks! 🙂

tonsky11:03:08

I also don’t think it’s a good practice on its own. You’d probably want to update matching fields, not remove them and inserting anew

rauh11:03:25

@linuss So I've been there a few times. I also did the remove/add thing for a while. And even carefully checked and then transacted the difference. All worked well... until it didn't. Lots of bugs. Much easier is to give those child elements an identity.

tonsky11:03:25

but then, of course, you’ll have a problem of diffing

rauh11:03:42

Often, by just giving them a composite key.

tonsky11:03:51

yes, identity is plain and simple

rauh11:03:26

Then all the upserts work really well and lots of headaches are gone. All that needs to be done, is to just always give them some composite key that identifies them.

tonsky11:03:56

great advice, thx Andre!

tonsky11:03:22

I might suggest form/id + field/name as a composite key

Aron11:03:56

I am trying to update a value in datascript. I have empty database with schema:

"DB_IDENT": {
    ":db/unique": ":db.unique/identity"
  },
  "current": {
    ":db/valueType": ":db.type/ref"
  }
and I am writing a function:
function setMyAddress(db, myAddr, oldAddr=null){
    return ds.db_with(db, vector(vector(DB_RETRACT, vector("DB_IDENT", "myAddr") , "current", toClj({"myAddr": oldAddr})),
                                 vector(DB_ADD, vector("DB_IDENT", "myAddr") , "current", toClj({myAddr}))))
}
and it is sayign that "Expected number or lookup ref for entity id, got {"myAddr" nil}"

Aron11:03:02

what am I doing wrong?

tonsky11:03:46

If you want to remove a ref, just put it's id in the value position

tonsky11:03:00

Right now you are putting whole map there

tonsky11:03:36

When you insert a map into attribute which is marked as ref in a schema, it will be expanded into whole new entity automatically

tonsky11:03:21

And the original entity will just store it's db/id as the value of ref attribute

tonsky11:03:04

But on retraction theres no magic, you have to delete what you want to delete, exactly as it's stored

tonsky11:03:42

That's why it asks about entity id or lookup ref. It can't delete a map because a map is not stored there

Aron11:03:02

thanks, i see now

Aron11:03:28

Unknown operation at [[:db/retract ["DB_IDENT" "myAddr"] "current" 4]], expected :db/add, :db/retract, :db.fn/call, :db.fn/retractAttribute or :db.fn/retractEntity"

Aron11:03:06

i am confused now

Aron11:03:51

oh, nvm, i had another vector wrapping it, sorry

linuss12:03:08

@tonsky @rauh The key approach works marvelously, thanks a lot!!

Aron12:03:44

interesting that we had basically the same question one after the other

Aron12:03:06

i tried cas too, but it's not available from datascript-mori i think 😞