realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.72k stars 564 forks source link

Implementation of Array of Arrays in a schema #5097

Open muddy-alex opened 1 year ago

muddy-alex commented 1 year ago

How frequently does the bug occur?

All the time

Description

I'm trying to implement an array of arrays (A GeoJSON LineString).

This is supported in MongoDB, BSON Schema (when I generate a schema), but I'm unable to model the schema in the JS SDK.

I've attempted to use a double[][] and a mixed[] but both don't seem to work.

i.e.

export const LineString = {
  name: 'LineString',
  embedded: true,
  properties: {
    type: { type: 'string', default: 'LineString' },
    coordinates: 'mixed[]',
  },
};

Any suggestions on how I model this?

Stacktrace & log output

No response

Can you reproduce the bug?

Yes, always

Reproduction Steps

No response

Version

11.1.0

What SDK flavour are you using?

Atlas Device Sync

Are you using encryption?

No, not using encryption

Platform OS and version(s)

Android

Build environment

Which debugger for React Native: ..

Cocoapods version

No response

kneth commented 1 year ago

Thank you for opening the issue. It is correct that we don't support arrays of arrays. And mixed value cannot be an array unfortunately.

We see requests for GeoJSON support (for example https://github.com/realm/realm-js/issues/4783), and we are considering how to add it. I can't give you a timeline for it.

kneth commented 1 year ago

@muddy-alex I will leave the issue open - but on our backlog - as I hope we will have a chance in the future to add support for it.

muddy-alex commented 1 year ago

Great! Thanks for your help. We'd really love this feature!

For anyone stumbling across this post, our solution is to keep both GeoJSON objects and an Realm Compatible objects in our documents...

export const RealmCoord = {
  name: 'Coord',
  embedded: true,
  properties: {
    latitude: 'double',
    longitude: 'double',
  },
};

export const RealmLineString = {
  name: 'RealmLineString',
  embedded: true,
  properties: {
    type: { type: 'string', default: 'LineString' },
    coordinates: 'Coord[]',
  },
};

And utilise hooks on our ORM (mongoose) where the documents are initially created to keep them in sync. (or on read hooks if created in Realm)

schema.post('validate', doc => {
  doc._realm_waypoints = {
    type: doc.waypoints.type,
    coordinates: doc.waypoints.coordinates.map(coordinatesToRealmCoordinates)
  }
});
ianpward commented 1 year ago

@muddy-alex Product for Realm & Device Sync here. I am interested in building this feature - I'd love to pick your bring on your use case if you're keen. If you could drop me a line at ian.ward@mongodb.com and we can set up a time to chat.

danielgabor99 commented 1 year ago

Hello,

I created a point object:

class GeoPoint: EmbeddedRealmObject{
    var latitude: Double = 0.0
    var longitude: Double = 0.0
}

and I used as a polygon list: var polygonList: RealmList<GeoPoint> = realmListOf()

danielgabor99 commented 1 year ago

Now I just want a method that can check if a point is inside a polygon.

How do you think that I should do that?

muddy-alex commented 12 months ago

I've just seen your team has added Geospatial support in v12! Woo!

In your documentation (https://www.mongodb.com/docs/realm/sdk/node/model-data/data-types/geospatial/#geopoint) you mention a way of modelling a GeoJSON Point.

// Implement `CanonicalGeoPoint`
// for convenience when persisting geodata.
class MyGeoPoint implements CanonicalGeoPoint {
  coordinates!: GeoPosition;
  type = "Point" as const;

  constructor(long: number, lat: number) {
    this.coordinates = [long, lat];
  }

  static schema: ObjectSchema = {
    name: "MyGeoPoint",
    embedded: true,
    properties: {
      type: "string",
      coordinates: "double[]",
    },
  };
}

Is there any way of modelling a LineString in v12?

correalm commented 11 months ago

I recently worked on this. The way we found this to work was to create the object as follows:

{
  "title": "geo_point",
  "bsonType": "object",
  "properties": {
    "type": {
      "bsonType": "string"
    },
    "coordinates": {
      "bsonType": "array",
      "items": {
        "bsonType": "double"
      }
  }
},
  "required": ["type"]
}

Result:

Screenshot 2023-09-25 at 17 58 06

muddy-alex commented 11 months ago

Thanks, however its a LineString I'm trying to implement natively in realm.

selina commented 7 months ago

+1, would also love to see LineString natively implemented in realm!

kneth commented 1 month ago

From v12.9.0 a mixed property can be a list. An array of an array can be done by declaring an list of mixed in the schema, and assign an array to a list element.