I have a unit test I am trying check the field but cannot find anything in the jest documentation to ignore the one value in this case, randomNumber.
const expected = [
{
model: 'string',
type: 'string',
randomNumber: 43,
name: 'string',
},
]
The random number changes every test so I can't hard code the test to check that number. I would like to test to make sure the expected array has all of the fields, but ignore the values.
const requiredKeys = ["model", "type", "randomNumber", "name"];
const actual = [
{
model: 'string',
type: 'string',
randomNumber: 43,
name: 'string',
},
{
type: 'string',
randomNumber: 43,
name: 'string',
},
]
actual.forEach(x => {
const keys = Object.keys(x);
const hasAllKeys = requiredKeys.every(key => keys.includes(key));
expect(hasAllkeys).toBeTruthy();
});
You can do something along the lines of this
const data = {
model: 'string',
type: 'string',
randomNumber: 43,
name: 'string',
}
const dataExpected = {
model: 'string',
type: 'string',
name: 'string',
}
const {randomNumber, ...randomNumOmittedData} = data;
expect(randomNumOmittedData).toEqual(dataExpected);
Related
How do I implement this properly?
const tree = buildTree(1, shuffleArray([
{ type: 'string', source_id: 1, name: 'foo', value: 'asdf' },
{ type: 'integer', source_id: 1, name: 'bar', value: 123 },
{ type: 'object', source_id: 1, name: 'nested', value: 2 },
{ type: 'object', source_id: 2, name: 'nested', value: 3, array: true },
{ type: 'boolean', source_id: 3, name: 'random', value: true },
{ type: 'string', source_id: 3, name: 'another', value: 'hello' },
{ type: 'object', source_id: 2, name: 'nested', value: 4, array: true },
{ type: 'boolean', source_id: 4, name: 'random', value: false },
{ type: 'string', source_id: 4, name: 'another', value: 'world' },
{ type: 'object', source_id: 2, name: 'nested', value: 5, array: true },
{ type: 'boolean', source_id: 5, name: 'random', value: true },
{ type: 'string', source_id: 5, name: 'another', value: 'awesome' },
]))
function buildTree(startId, array) {
const map = array.reduce((m, x) => {
m[x.source_id] = m[x.source_id] ?? {}
if (x.array) {
m[x.source_id][x.name] = m[x.source_id][x.name] ?? []
m[x.source_id][x.name].push({ id: x.value })
} else {
m[x.source_id][x.name] = x.value
}
return m
}, {})
// ??? getting lost...
}
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array
}
where the "expected tree" would be something like this:
const expectedTree = {
id: 1,
foo: 'asdf',
bar: 123,
nested: {
id: 2,
nested: [
{
id: 3,
random: true,
another: 'hello'
},
{
id: 4,
random: false,
another: 'world'
},
{
id: 5,
random: true,
another: 'awesome'
}
]
}
}
The shuffleArray is just to show that the records could be in any order, and the id (source_id) property is not necessarily in incremental order (actually in my case they are UUIDs with the hierarchy not really in any particular order). Each "record" in buildTree is a "property" record basically like this:
create table object_properties {
uuid id;
uuid source_id; // the object which has this property
string name; // the property name
uuid value; // the property value object
}
// ...and same for boolean, integer, etc. properties
create table string_properties {
uuid id;
uuid source_id; // the object which has this property
string name; // the property name
string value; // the property value string
}
In my buildTree I can kind of imagine creating a map from the source_id (the base object node which has property name), to the names, to the values. But then maybe iterating over the source IDs, looking for objects nested inside the name values, and converting them to objects instead of just IDs. But this is getting hard to comprehend and I'm sure there is an easier way somehow.
What is an algorithm to build an "object tree" from this flat list of records?
In my situation, I am fetching a bunch of deeply nested property objects, recursively, and need to stitch back together an object tree out of them.
It looks like the name "nested" plays a special role. When it occurs, the corresponding value property does not hold a literal value to assign to the named property (as is the case with other names), but is a reference to an existing source_id value.
This means your code needs to deal with that name specifically and then establish the parent-child relationship. This relationship is further influenced by the array property.
I would define buildTree as follows, making use of a Map, which is built first using its constructor argument:
function buildTree(startId, arr) {
const map = new Map(arr.map(({source_id}) => [source_id, { id: source_id }]));
for (const {source_id, name, value, array} of arr) {
if (name !== "nested") {
map.get(source_id)[name] = value;
} else if (array) {
(map.get(source_id).nested ??= []).push(map.get(value));
} else {
map.get(source_id).nested = map.get(value);
}
}
return map.get(startId);
}
// Code below has not changed
function shuffleArray(array) { for (var i = array.length - 1, j, temp; i > 0; i--) {j = Math.floor(Math.random() * (i + 1));temp = array[i];array[i] = array[j];array[j] = temp;} return array;}
const tree = buildTree(1, shuffleArray([{ type: 'string', source_id: 1, name: 'foo', value: 'asdf' },{ type: 'integer', source_id: 1, name: 'bar', value: 123 },{ type: 'object', source_id: 1, name: 'nested', value: 2 },{ type: 'object', source_id: 2, name: 'nested', value: 3, array: true },{ type: 'boolean', source_id: 3, name: 'random', value: true },{ type: 'string', source_id: 3, name: 'another', value: 'hello' },{ type: 'object', source_id: 2, name: 'nested', value: 4, array: true },{ type: 'boolean', source_id: 4, name: 'random', value: false },{ type: 'string', source_id: 4, name: 'another', value: 'world' },{ type: 'object', source_id: 2, name: 'nested', value: 5, array: true },{ type: 'boolean', source_id: 5, name: 'random', value: true },{ type: 'string', source_id: 5, name: 'another', value: 'awesome' },]))
console.log(tree);
Note that the order in which objects are pushed into arrays is defined by the original order of the objects. Since this input array is shuffled, the output may show arrays in different ordering on separate runs. Something similar holds for object keys (see Object property order)
You should try Array.prototype.group(). Please refer below document.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/group
const inventory = [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
{ name: 'bananas', type: 'fruit', quantity: 0 },
{ name: 'goat', type: 'meat', quantity: 23 },
{ name: 'cherries', type: 'fruit', quantity: 5 },
{ name: 'fish', type: 'meat', quantity: 22 }
];
const result = inventory.group(({ type }) => type);
/* Result is:
{
vegetables: [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
],
fruit: [
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "cherries", type: "fruit", quantity: 5 }
],
meat: [
{ name: "goat", type: "meat", quantity: 23 },
{ name: "fish", type: "meat", quantity: 22 }
]
}
*/
async function createDatabase() {
addRxPlugin(RxDBReplicationCouchDBPlugin);
addPouchPlugin(PouchdbAdapterIdb);
addRxPlugin(RxDBLeaderElectionPlugin);
const database = await createRxDatabase({
name: 'dictionaries',
storage: getRxStoragePouch('idb')
});
await database.addCollections({
dictionaries: {
schema: {
title: 'dictionary',
description: '',
version: 0,
primaryKey: 'id',
type: 'object',
keyCompression: false,
properties: {
id: {
type: 'string',
maxLength: 100,
},
name: {
type: 'string',
minLength: 1,
maxLength: 30,
},
},
required: ['id', 'name']
}
}
})
}
When I pass some value as an id, it is used as part of an auto-generated key:
const db = await createDatabase();
await db.dictionaries.newDocument({
id: 'bar',
name: 'English'
}).save(); // _doc_id_rev inside the db would be of format "bar::<auto-generated value>"
My question is is there any way to say RxDB that generating id's values for dictionaries is of its own concern or my single option is always to provide a dummy value, such as bar?
I want to combine two schemas in realm db and perform operations on them, just like join in sql. But i don't know how to do it. I did not
List item
understand anything from the document. How can I do that?I have two schematics
const barkod = {
name: 'barkod',
properties: {
StokNo: { type: 'int', indexed: true },
Barkod: { type: 'string', indexed: true },
Birim: 'string',
BarkodTipi: 'string',
Aciklama: 'string?',
YStokNo: 'int'
}
// primaryKey: 'Barkod',
}
const stok = {
name: 'stok',
primaryKey: 'StokNo',
properties: {
StokNo: 'int',
StokAdi: { type: 'string', indexed: true },
StokKisaAdi: 'string',
StokKodu: 'string',
StokTanimi: 'string',
GrupKodu: 'string',
KdvOranP: { type: 'int', default: 0 },
KDVOranT: { type: 'int', default: 0 },
OzelKodu1: 'string',
OzelKodu2: 'string',
OzelKodu3: 'string'
}
}`enter code here`
and I want to join these two schemas
'SELECT Stok.StokAdi, Barkod, StokNo FROM ? AS Barkod JOIN ? AS Stok ON Barkod.StokNo = Stok.StokNo',
I found the solution to the problem. And this is how I did it. Hope it helps for those who have this problem.
const CarSchema = {
name: 'Car',
properties: {
make: 'string',
model: 'string',
miles: {type: 'int', default: 0},
},
};
const PersonSchema = {
name: 'Person',
properties: {
name: 'string',
birthday: 'date',
cars: 'Car[]',
// picture: 'data?' // optional property
},
};
const exp1 = () => {
var person;
Realm.open({schema: [CarSchema, PersonSchema]})
.then(realm => {
realm.write(() => {
person = realm.create('Person', {
name: 'ayşegül',
birthday: new Date(1995, 11, 25),
// cars: 'Car[]',
});
console.log(person.cars);
let carList = person.cars;
carList.push({make: 'Honda', model: 'model1', miles: 100});
carList.push({make: 'Toyota', model: 'model2', miles: 200});
console.log(person);
});
})
.catch(error => {
console.log(error);
});
};
I am trying to insert my nested object to Realm with To-One Relationships method, but I got an unexpected result where all value of my nested object is the same thing as the value from the first of my nested object that has been Relationship
This is my schema looks like
const PhotoSchema = {
name: 'CUSTOMER_PHOTOS',
properties: {
base64: 'string'
}
};
const TimeSchema = {
name: 'CUSTOMER_TIMES',
properties: {
warranty: 'float',
finish: 'float'
}
};
const MainSchema = {
name: 'CUSTOMERS',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
photo: {type: 'CUSTOMER_PHOTOS'},
time: {type: 'CUSTOMER_TIMES'},
}
};
And try to insert some data like this
import Realm from 'realm';
Realm.open({
path: 'mydb.realm',
schema: [PhotoSchema, TimeSchema, MainSchema]
})
.then((realm) => {
realm.write(() => {
realm.create('CUSTOMERS', {
id: Date.now(),
name: 'John',
photo: {
base64: 'ImageBase64'
},
time: {
warranty: 31,
finish: 7
}
})
})
})
.catch((error) => {
console.error(error)
});
The process of inserting data is successfully BUT I got unexpected result when successfully get that data from Realm
Unexpected Result in console.log()
{
id: 1601335000882,
name: "John",
photo: {
base64: "ImageBase64"
},
// This value is the same as PhotoSchema
time: {
base64: "ImageBase64"
}
}
I want to the actual result like this
{
id: 1601335000882,
name: "John",
photo: {
base64: "ImageBase64"
},
time: {
warranty: 21
finish: 7
}
}
I there anything wrong with my code? The Documentation is not too detail about the method, the explanation and the example is just like one word
UPDATE:
I got an unexpected result only in the console.log() and if I try to access the property directly like MY_DATA.time.warranty the result is what I expected
The Answer is: No
To-One Relationships method is not only for one Schema, and Thanks to Angular San for showing an example of Inverse Relationships method.
Try Inverse Relationships
I got an expected result with Inverse Relationships method. In this method, you have to add one property that connected to Main Schema and I want to call this a combiner property
const PhotoSchema = {
name: 'CUSTOMER_PHOTOS',
properties: {
base64: 'string',
combiner: {type: 'linkingObjects', objectType: 'CUSTOMERS', property: 'photo'}
}
};
const TimeSchema = {
name: 'CUSTOMER_TIMES',
properties: {
warranty: 'float',
finish: 'float',
combiner: {type: 'linkingObjects', objectType: 'CUSTOMERS', property: 'time'}
}
};
const MainSchema = {
name: 'CUSTOMERS',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
photo: 'CUSTOMER_PHOTOS',
time: 'CUSTOMER_TIMES',
}
};
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Sorry if this is a bit confusing, but I have this array:
[
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
]
How would I turn it into
{
notes: '[]',
reminders: '[]'
}
? Here's the logic: Any index with a default property, set the key in the new object to the index's name, and set the value to the index's default.
You can make it with reduce
var array = [
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
]
var result = array.reduce((prev, el) => {
if (el.default) {
prev[el.name] = el.default
}
return prev;
},{})
console.log(result);
You can use filter with Object.keys().
// Your initial array
const initialArray = [{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
// Array just with items that haves a default value
const itensWithDefaultValue = initialArray.filter(item => Object.keys(item).includes('default'));
// Object to save items
let objectWithValues = {};
// Save items in object with name and you default value
itensWithDefaultValue.map(item => objectWithValues[item.name] = item.default);
console.log(objectWithValues);
Hope this helps!
const data = [
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
const result = Object.fromEntries(
data
.filter(it => "default" in it)
.map(it => ([it.name, it.default]))
);
console.log(result);
Use reduce:
const arr = [{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
const obj = arr.reduce((acc, curr) => curr.default ? { ...acc,
[curr.name]: curr.default
} : acc);
console.log(obj);
You could spread new objects into a single object.
var data = [{ name: 'id', type: 'string', primary: true }, { name: 'notes', type: 'text', default: '[]' }, { name: 'reminders', type: 'text', default: '[]' }],
result = Object.assign({}, ...data.map(({ name, default: d }) => d && { [name]: d }));
console.log(result);