write json to realmdb schema - javascript

I need to save a json in a property of my schema, my schema:
export default class ListSchema {
static schema = {
name: 'Listas',
primaryKey: 'id',
properties: {
id: 'string',
name: 'string',
contents: 'string', // I need to save here, currently I left string
}
}
}
code that saves the list:
async function SaveList() {
const data = {
id: String(Date.now()),
name: List,
contents: JSON.stringify(AllTask) // I need to save json here
}
const realm = await getRealm()
realm.write(() => {
realm.create('Listas', data)
})
}
my json n has a definite size, and it goes something like this:
[{id: 'value', name:'value'}, {id: 'value', name:'value'} ...]
what should my schema look like?

I'm using Realmdb in production with React Native and had the same doubt some time ago.
Basically you have two ways to do it.
The first and the more simple is convert your schema using JSON.stringify and save it in your field with type string, (Like you did) but when you wish get this value again, you will to convert again using JSON.parse, is boring but works well you have just to remeber.
The second option is create another schema and use it to insert values with object format.
const CarSchema = {
name: 'Car',
properties: {
make: 'string',
model: 'string',
miles: {type: 'int', default: 0},
}
};
const PersonSchema = {
name: 'Person',
properties: {
name: 'string',
cars: {type: 'list', objectType: 'Car'},
}
};
Above, we have two schema and if we insert a new data we have to do something like this.
realm.write(() => {
realm.create('Person', {
name: 'Joe',
// nested objects are created recursively
car: {make: 'Honda', model: 'Accord', drive: 'awd'},
});
});
This way is more eficient but is more hard to maintain the code.
Today we use the option 1, because is more simple and just one schema.
I hope that it help you.

Related

Mongodb find documents with given field value inside an array and its id in another array inside the same document

My data model:
{
_id: ObjectId,
persons:[{
_id: ObjectId,
name: String,
...
}],
relations: [{
type: String,
personId: ObjectId,
...
}],
...
}
Here's my issue:
I am trying to find documents where person's name is x and it's _id is inside the relations array (personId) with a given type.
Example:
My data:
[{
_id:"1",
persons:[{
_id:"1",
name: "Homer"
},
{
_id:"2",
name: "Bart"
}],
relations: [{
type:"House_Owner",
personId: 1,
}],
}]
Request_1:
Find all documents where "Homer" is the house owner
Result:
[{
_id:"1",
...
}]
Request_2:
Find all documents where "Bart" is the house owner
Result:
[]
Any help would be appreciated.
The only solution I see here is to do the find operation with the given name value and after that filter the mongodb result.
PS: I cannot change the existing data model
EDIT:
I found a solution to do this by using $where operator with a javascript function but I am not sure that's the most efficient way.
db.myCollection("x").find({
$where: function() {
for (const relation of this.relations) {
if(relation.type === "House_Owner") {
for (const person of this.persons) {
if(person.name === "Homer" && person._id.equals(relation.personId)) {
return true;
}
}
}
}
}
})
You can do something like this:
const requiredName="x"
const requiredId = "id"
await yourModel.find({$and:[{"relations.personId":requiredId },{"persons.name":requiredName}]})

How to populate field in all objects of an array response?

I have a User model:
const userSchema = new Schema({
username: String,
email: String,
_id: generated
})
and a Project model:
const projectSchema = new Schema({
owner: { type: Schema.Types.ObjectId, ref: 'User' },
name: String,
_id: generated
})
I am using a request to get all projects, and would like to then populate the 'owner' field of each project with the corresponding user (or, even better, their username)
Project.find()
.populate('owner')
.then((allProjects) => {
console.log(allProjects);
res.status(200).json(allProjects);
})
The response from the find(), as seen in the console.log() is an array of objects, on which populate seems to have had no effect:
[{
_id: 4kal5mah5lam6la2lam40am3,
owner: 28eqo29roqi5lqmdka91ma01,
name: Project1
},
{
_id: 0akm40am593na7n4fnau25a,
owner: 85jan5l60oq23la1p07d8q2,
name: Project2
}]
I've tried many things with the populate call and its parameter but to no effect. The code runs, just doesn't populate the field. Any ideas?
Many thanks!

Normalizr: Identifying entities by type rather than schema for polymorphic mappings

For a polymorphic schema such as Union in Normalizr, for schema definitions and data:
const data = { owner: { id: 1, type: 'user', name: 'Anne' } };
const user = new schema.Entity('users');
const group = new schema.Entity('groups');
const unionSchema = new schema.Union({
user: user,
group: group
}, 'type');
const normalizedData = normalize(data, { owner: unionSchema });
normalized data takes the form:
{
entities: {
users: { '1': { id: 1, type: 'user', name: 'Anne' } }
},
result: { owner: { id: 1, schema: 'user' } }
}
The entities are keyed on the schema key, in this case, users, but the result object includes only the key for the schema in the UnionSchema definition. This can make it difficult to match up the elements later without full denormalization.
Is there some better way to normalize such data with normalizr to make it easier to pull the entity from the entities, given the result? For my purposes, ideally, data could be normalized from something like:
const data = { owner: { id: 1, type: 'users', name: 'Anne' } };
to
{
entities: {
users: { '1': { id: 1, type: 'users', name: 'Anne' } }
},
result: { owner: { id: 1, type: 'users' } }
}
Note that the type matches the entity key (that is pretty trivial), and the name of the key in result is type (more of a pain if you want to do it with more complex data). I suspect that that sort of normalization would make it harder to denormalize, but I'm interested in normalization only.
Got an answer on this:
https://github.com/paularmstrong/normalizr/issues/281
Apparently, the behavior is intentional and is not going to change--there is no way to use Normalizr to do what I asked.

Storing Javascript Array of Objects in Mongo DB using Mongoose

I have an array of the form [{key: ..., type: ..., value: ...}] and want to store it in the fields field in the following schema:
var articleSchema = mongoose.Schema({
name: {
type: String,
unique: true,
required: true
},
updated: {
type: Date,
default: Date.now
},
pageviews: {
type: Number,
default: 0
},
fields: [{
key: String,
type: String,
value: String
}],
image: String
});
I am doing this as follows, my Javascript array referenced as keyValueObj
Article.findOneAndUpdate(
{ name: articleName },
{
fields: keyValueObj
},
{ upsert: true },
callback
);
However, all that is stored in the database in the fields field is an array of strings like this: ["[object Object]"]
How can I store my Javascript array so that it matches my mongoose schema correctly?
I was able to fix this using Molda's idea of using a separate schema.
The updated fields field in the articleSchema now looks like this:
fields: [{
type: Schema.Types.ObjectId,
ref: 'Field'
}]
I then converted the array to an array of schema objects, like this:
keyValueObj = keyValueObj.map(function(fieldObj){
return new Field({
key: fieldObj.key,
type: fieldObj.type,
value: fieldObj.value
});
});
I was then able to store keyValueObj the was doing it in the initial code.

Nested Javascript Object : recursion and "complex" transformation (with lodash)

I apologize in advance for the complex example here; I tried to trim it down as much as I could to illustrate what I try to achieve
I have a complex structure that I need to traverse and transform based on some conditions; Here's an (short) example of the structure that should cover most scenarios:
{ PROP1: {
metadata: Object, // somewhere deeper in metadata I have a `value` key
parent: { $ref: String },
employee: {
parent: { $ref: String },
id: String,
metadata: Object,
products: {
metadata: Object,
model: { $ref: String },
type: 'array',
value: ["String", "String" , "String"] ,
[...]
},
model: {
id: String,
email: {
metadata: Object,
value: 'a#b.com',
type: 'string',
validity: Object,
[...]
},
name: {
firstName: {
metadata: Object,
value: 'John',
type: String,
validity: Object,
[...]
},
lastName: {
metadata: Object,
value: 'Smith',
type: String,
validity: Object,
[...]
},
}
},
operations: {
id: String,
items: [
{ action: {value: "UPDATE", model: {$ref: String }, [...] },
{...}
],
metadata: Object,
[...]
}
}
},
PROP2: {
// similar as PROP1
},
[... and so on ...]
}
I basically need to clean that up before sending it to the backend;
Whenever a value contains $ref, I don't want the key/val pair (e.g.: PROP1.parent is of no use and can be omitted)
whenever a value contains value, I need to omit everything else and move the value of value as the value of key (e.g.: PROP1.employee.products should equal ['String', 'String', 'String'])
keys like id, metadata, validity (etc) can be completely omitted regardless of its content
So the end result should be along those lines:
{ PROP1: {
employee: {
products: ['item','item','item'],
model: {
email: 'a#b.com',
name: { firstName: 'John', lastName: 'Smith'},
},
operations: [
{action: 'UPDATE'}
]
}
},
PROP2: { ... }
}
I tried lots of different approaches using different lodash methods but couldn't wrap my head around this...
Any help will be greatly appreciated
Thanks
In pseudo code, try something like this. Implement the specifics and post more info when you run into trouble.
var ignoreKeyArray = ["id", ...] // keys to ignore and remove
var newJSON = "{}";
for (property in JSON) {
var newProp = parseJSON(key, property);
insert newProp in newJSON object
}
var parseJSON = function (key, jsonBlob) {
if (key in ignoreKeyArray || jsonBlob contains value "$ref")
return "";
var jsonOut = key + ": {}";
for (child in jsonBlob) {
add parseJSON(child) to jsonOut;
}
return jsonOut;
}
If you have any questions, comment so I can extend the answer and clarify.

Categories

Resources