realm / realm-js

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

Convert Results to Array of Objects! #280

Closed dcflow closed 8 years ago

dcflow commented 8 years ago

Hi,

We may need sometimes to have every object with every property. What should be a clean way of doing this instead of nested loops.

Thank You!

alazier commented 8 years ago

We definitely plan to add this as well as other Array methods. Until we add this you should be able to use the Array method directly. Something like: Array.prototype.slice.call(results, startIndex, endIndex) should hopefully work.

alazier commented 8 years ago

Hopefully this worked for you.

dcflow commented 8 years ago

Hey @alazier sorry for the late response. Now I got to try it and it does convert the List into an Array but you cannot call for example map on the array since the objects inside are still lazy Realm Objects. One way that works is to call the lodash collection functions _.map(array, ..). It would be great if there was a function that would go deep into every object property and initialize it. Anyway thanks for your help. :)

ismdcf commented 7 years ago

@aiflow can you elaborate on how you used the lodash _.map function

romanlv commented 7 years ago

This converts it to array of plain objects result.map(x => Object.assign({}, x))

L3V147H4N commented 7 years ago

any news about this method? for some reason using .map or .values or .entries on a realm object on android is extremely slow, even on DEV = false (realm 1.2.0 - RN 0.40)

i6mi6 commented 6 years ago

Why is this closed?

MihaelIsaev commented 6 years ago

result.map(x => Object.assign({}, x)) doesn't work! it converts it to array of empty objects

anglol commented 6 years ago

With lodash you can do something like :

const results = realm.objects('ModelName').filtered('favorite == true'); const arrayResults = _.values(results)

https://lodash.com/docs/4.17.4#values

MihaelIsaev commented 6 years ago

As for me only Array.from() works fine

let query = realm.objects(Realm.carBrand)
let array = Array.from(query)
LingboTang commented 6 years ago

@alazier Specifically, I want to copy a realm list field to a json field. For ex, if I have:

export const userSchema = {
  name: 'User',
  primaryKey: 'id',
  properties: {
    id: 'string',
        user_id: 'string',
    list_of_house_id: 'int[]',
  }
}

and I want to copy this list_of_house_id to a javascript list: js_list_of_house_id. I tried Array.prototype.slice.call(list_of_house_id), but it is extremely slow, for just 2500 entries, it takes roughly 10 seconds to copy all the entries to js_list_of_house_id. I noticed that when I query the user from realm storage, the field list_of_house_id is a Proxy object, so is it possible to do a simple copy as js_list_of_house_id = list_of_house_id.Collectionor js_list_of_house_id = list_of_house_id.target? Basically I just need to know what's the correct name of the properties that I need to get from the Proxy. Because I tried to call list_of_house_id.List, it is undefined.

paulbrittain commented 6 years ago

This is still a big problem

nirinchev commented 6 years ago

Why is it a problem? Did none of the proposed solutions work for you?

brancooo1 commented 6 years ago

@nirinchev It's a problem. Big problem, for consideration to not use Realm.

Imagine you have an object which has property of array of objects. You set everything properly in Realm schema, you store there the array, everything works great till now. Now, you fetch it from Realm and you get your object with the property which isn't array but an Object! :-1:

I wanna to be able to fetch data from the Realm and get from there what I defined! :+1: and then send it over network and write it on another device which has the same schema.

How this should be done, can you propose a solution?

LingboTang commented 6 years ago

I remember when I used one another noSQL (can't remember which one specifically), I have my application layer implemented in java. When I fetch data from that noSQL, I also get anonymous type of object even if I defined the type when I stored it. However, I was able to get the entire chunk of data, and convert it back to the defined type with a simple util function. When I fetch data from realm, because of the protection of Proxy, I almost have to iterate through the List to get all the entries in that List converted. If I know how realm defined handlers for List type of [[Target]], it will be easier for us to convert anyway.

brancooo1 commented 6 years ago

@LingboTang you're absolutely right!

Do you have on your mind any workaround which would work for our use case? use case: I wanna get object (with property of type array) which will be as is described by schema.

nirinchev commented 6 years ago

@brancooo1 the schema describes a list which is what you get. The list has API surface that is similar to the API surface of regular arrays, so you can use it with most functions that expect arrays. If you want to convert it to an array, you can use lodash or Array.from (or even a simple for loop).

Is it possible you're being confused by the shorthand declaration of list properties that uses the square brackets syntax which you interpret as array?

brancooo1 commented 6 years ago

By Array.from you will convert just the very top property/object, not all the nested properties.

@nirinchev and how to use it to store it again? As the use case which I described? If you fetch such an object from Realm. Send it to to another device. You're unable to save it again. It will throw an error xxx.yyy must be of type 'Yyy[]', got 'object' ([object Object])

nirinchev commented 6 years ago

Extracting all nested properties is a problem without a good generic solution because you can have cycles in your graph which are hard to be broken in a predictable and deterministic manner.

I think it's best to open a new issue with a repro case and a good explanation of what you're trying to achieve so we can provide guidance. Discussing on a closed issue that is marginally related is going to be suboptimal. The basic problem of converting a list (or results) to an array is solved by the approaches outlined here and it doesn't make sense to reopen the issue to track the broader problem.

LingboTang commented 6 years ago

Functionality wise speaking both lodash and Array.from work, but they work with a significantly slow performance when I have just relatively small workload. I've already posted what I met in the previous comment.

LingboTang commented 6 years ago

@brancooo1 My work around for that is dirty. Basically, when you store it to realm, you don't store it as a list of object, but you store it as a stringified json. So instead of defining your property as property: {type: 'list', objectType: 'SomeObjectType'} you define your property as: property: string and you stringify your list before you store it.

brancooo1 commented 6 years ago

I did workaround on the backend, but basically can be done anywhere if you use JSON.stringify and JSON.parse. It's not nice, but I have to parse it anyway, so I used the second parameter of the JSON.parse, and while parsing the json, I'm parsing it to the arrays. Mostly the lists are plurals, and you know their names, so the solution is like:

    let parsed = JSON.parse(message, (key, value) => {
      if (key === 'customers' || key === 'items' .... ) {
        return Object.values(value);
      }
      return value;
    });

message is fetched data from Realm. Parsed data doesn't have "Realm lists" but an arrays.

nirinchev commented 6 years ago

You do realize this will cause a stack overflow if you have cycles in your object graph, right?

brancooo1 commented 6 years ago

It's the price for the workaround. JSON.stringify cannot handle cycles anyway. This way, you can write your own JSON parser which will handle (omit) circular dependencies (https://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json)

LingboTang commented 6 years ago

screen shot 2018-04-13 at 3 00 25 pm When I iterate through it and tried to get data field by keys from the realmObject, it takes unreasonably large amount of time.

martsie commented 6 years ago

@LingboTang I believe that is a separate issue to Realm performing poorly with react-native debugger.

LingboTang commented 5 years ago

@martsie Realm is fast in terms of store and query object, correct. React-Native debugger will make Realm perform worse, correct. I'm just using this chrome debugger as a simple way to display the problem, might not be very accurate, I apologize. However, when I turned off the debugger and ran it with release build, it still took large amount of time to retrieve one data field from one realmObject. That is the problem.

rottenoats commented 5 years ago

Object.values does not work either, I get an array of empty objects.

Udbhav12 commented 5 years ago

result.map(x => Object.assign({}, x)) worked for me till RN 0.57.8. Unfortunately It is not working in RN 0.59.0

ferrannp commented 5 years ago

Same for me on 0.59.x and Android. Object.values returning empty array + result.map(x => Object.assign({}, x)) not working either. I guess is due new JSC?

cyphire commented 5 years ago

I am trying to get this working now that I am using a list and need to update it.

It's easy enough to take the list and turn it into a simple array of objects by:

let newArray = JSON.parse(JSON.stringify(item.images))

where my record is item and images is the List variable.

then write back the newArray in a write transaction...

pedrobertao commented 4 years ago

Is there any news or the best approach to solve use those objects ?

pedrobertao commented 4 years ago

We are using Arry.from(arr, item => ({...item}))

cyphire commented 4 years ago

I found it the easiest to just do JSON.parse(JSON.stringify(arr)) or something like that. This will make the array an array of objects, not an array of realm objects. But note that I found after weeks of work I couldn't stop realm from still interfering in the debugger.... Even if i closed the database....


Brian B. Canin brian.canin@gmail.com

858-945-5601 (cell)

On Fri, Jun 14, 2019 at 3:04 PM Pedro Bertao notifications@github.com wrote:

We are using Arry.from(arr, item => ({...item}))

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/realm/realm-js/issues/280?email_source=notifications&email_token=AACSPBQDN22S6N4S27DJCYDP2PTVJA5CNFSM4B4MIZB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXXWGJQ#issuecomment-502227750, or mute the thread https://github.com/notifications/unsubscribe-auth/AACSPBWSEFDJMYLUJTU7UQ3P2PTVJANCNFSM4B4MIZBQ .

thanhluantl2304 commented 4 years ago

@brancooo1 so what was the final solution? I faced that problem too! Did your's method Json.Parse work? Please answer me! Thank you!

cyphire commented 4 years ago

So... Nothing in the end worked if you are talking about using realm.io (javascript).

The problem is that while you can get the data out by doing the parse / stringify above, and it creates a nice array, the realm.io is still there, even if you close the realm files and open / close the database. And while this exists, it makes debugging problematic.

What I do is just use realm, and do NOT use the debugger! I use Reactotron to show my state and console.log (which with reactotron means console.tron.log(). I've been doing react native so long, that the debugger, while nice, wouldn't be much help.

Good luck and write back if this doesn't help.

Best.

rdgomt commented 4 years ago

@cyphire Did you find a solution to debug offline? I can't connect to Reactotron while device has no internet connection. It limits some kind of tests.

andyyapwl commented 4 years ago

I got the same problem of trying to fetch the value as array instead of realm object. Will stick back to sqlite instead.

brancooo1 commented 4 years ago

Hey @thanhluantl2304 it's been quite long time ago. Back then, I used the above mentioned code

    let parsed = JSON.parse(realmResult, (key, value) => {
      if (key === 'customers' || key === 'items' .... ) {
        return Object.values(value);
      }
      return value;
    });

where customers, items were realm db atributes converted to javascript arrays.

thanhluantl2304 commented 4 years ago

Ya, thank @brancooo1 . I've also done that way but still wait for Realm to fix that. That's quite unconvenient!

JosefButzke commented 4 years ago

Hi guy, my solution was return a function with instance inside Schema:

//Schema
export default class UserSchema {
  static schema = {
    name: 'Users',
    primaryKey: 'id',
    properties: {
      id: {type: 'int', indexed: true},
      name: 'string',
      cr: 'int',
      data_nascimento: 'int',
      ghe: 'string',
      path: 'string',
      epis: 'Epis[]',
    },
  };

  get values() {
    return {
      id: this.id,
      name: this.name,
      cr: this.cr,
      data_nascimento: this.data_nascimento,
      ghe: this.ghe,
      path: this.path,
      epis: this.epis.map(e => e.values),
    };
  }
}

//call
const realm = await getRealm();
const response = realm.objects('Users').sorted('name');
console.tron.log(response.map(user => user.values));
ghost commented 3 years ago

Any native solution yet?

foxbit19 commented 3 years ago

No luck using Array.from on nested objects. I've work it out combining some of the suggested solutions:

rows = JSON.parse(JSON.stringify([...result]))

Hope it helps!

apppro123 commented 3 years ago

Is there any good solution for nested objects? And why is it not possible to return arrays in the first place/don't convert arrays to objects at all?

Thanks for any answer ;)

caiobiodere commented 3 years ago

@apppro123 that's a good question I wonder if they could come up with some realm code solution for this problem

ombogdan commented 2 years ago

Any native solution yet? Hey realm

scinfu commented 2 years ago

up

caiobiodere commented 2 years ago

There is a simple way for achieving this problem

const results = realm.objects('ModelName').filtered('');
const arrayResults = results.map((object) => object.toJSON())
ombogdan commented 2 years ago

it`s not working TypeError: object.toJSON is not a function. (In 'object.toJSON()', 'object.toJSON' is undefined)

чт, 16 сент. 2021 г. в 14:08, Caio Biodere @.***>:

There is a simple way for achieving this problem

const results = realm.objects('ModelName').filtered(''); const arrayResults = results.map((object) => object.toJSON())

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/realm/realm-js/issues/280#issuecomment-920805150, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIZPQK24GUWOIE2J6GX3MR3UCHFZ7ANCNFSM4B4MIZBQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

ombogdan commented 2 years ago

https://prnt.sc/1sf9046

чт, 16 сент. 2021 г. в 14:14, Bod'ka pavyk @.***>:

it`s not working TypeError: object.toJSON is not a function. (In 'object.toJSON()', 'object.toJSON' is undefined)

чт, 16 сент. 2021 г. в 14:08, Caio Biodere @.***>:

There is a simple way for achieving this problem

const results = realm.objects('ModelName').filtered(''); const arrayResults = results.map((object) => object.toJSON())

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/realm/realm-js/issues/280#issuecomment-920805150, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIZPQK24GUWOIE2J6GX3MR3UCHFZ7ANCNFSM4B4MIZBQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.