MongoDB multi-language modeling - node.js

I have built a schema that should handle the multi-language on MongoDB.
It looks something like that
name: 'product-en',
code: 'xyz',
translation: [
{
lang: 'ar',
name: 'product-ar'
},
{
lang: 'fr',
name: 'product-fr'
},
]
But let's say if I want to add a category for this product and also the category has a translation and I will use referencing so when i populate the document, the result will be something like that.
name: 'product-en',
code: 'xyz',
category: {
name: "category-en",
translation: [
{
lang: "ar",
name: "category-ar"
},
{
lang: "fr",
name: "category-fr"
}
]
},
translation: [
{
lang: 'ar',
name: 'product-ar'
},
{
lang: 'fr',
name: 'product-fr'
},
]
So, I'm using NestJS and I thought that I should use an interceptor to only apply the requested language so if the user wants the products in English, it will remove only the translation key, and if he wants it in Arabic it will search for the Arabic language in the translation array and merge its value in the name.
I tried to apply that with the merge method in Loadash and it worked but for the populated key which is category it won't cause it will only search for the doc.translation and won't care about doc.category.translation and if there is more like doc.pla.plapla.translation it won't know that it should merge it also.
So, what should I do to solve this issue?

Related

Dynamically index nested fields in mongoose

I would like to be able to index some nested fields in my mongodb using mongoose. The fields in question are the "name" and "description". They are in English and Arabic languages.
They look like this after creation:
"name": {
"en": "Trace Chandelier",
"ar": "نجفة"
},
"description": {
"en": "Steel canopy.",
"ar": "نجفة من الستاينلس ستيل و النحاس. بمكن تغيير الارتفاع."
}
The "en" and "ar" keys are added dynamically from the frontend or postman. More languages will be added in the future.
The schema look like this:
const productSchema = new mongoose.Schema({
name: {
type: Map,
of: String,
required: true
},
description: {
type: Map,
of: String,
required: true
}
}
});
I know in order to create an index in mongoose, it can be like this:
productSchema.index(
{
name: 'text',
description: 'text',
},
{default_language: "none", language_override: "none"}
);
I'd like to index these fields to be able to search for any string in them.
But I can't do name.en or name.ar. As I previously said that more languages will be added in the future.
How can dynamically index those fields?
Thanks in advance.

Gremlin NodeJS query returns different results than Groovy

I have a query that I originally wrote in the console:
g.V().hasLabel('group')
.has('type', 'PowerUsers')
.local(__.union(
__.project('group').by(__.valueMap().by(__.unfold())),
__.inE().outV().project('user').by(__.valueMap().by(__.unfold())))
.fold()).unfold().toList()
I get something like:
==>{group={owner=A, group_id=21651399-91fd-4da4-8608-1bd30447e773, name=Group 8, type=PowerUsers}}
==>{user={name=John, user_id=91f5e306-77f1-4aa1-b9d0-23136f57142d}}
==>{user={name=Jane, user_id=7f133d0d-47f3-479d-b6e7-5191bea52459}}
==>{group={owner=A, group_id=ef8c81f7-7066-49b2-9a03-bad731676a8c, name=Group B, type=PowerUsers}}
==>{user={name=Max, user_id=acf6abb8-08b3-4fc6-a4cb-f34ff523d628}}
==>{group={owner=A, group_id=07dff798-d6db-4765-8d74-0c7be66bec05, name=Group C, type=PowerUsers}}
==>{user={name=John, user_id=91f5e306-77f1-4aa1-b9d0-23136f57142d}}
==>{user={name=Max, user_id=acf6abb8-08b3-4fc6-a4cb-f34ff523d628}}
When I run that query with NodeJS, I was expecting to get a similar result, but I don't. I get something like this:
[ { group:
{ owner: 'A',
group_id: '21651399-91fd-4da4-8608-1bd30447e773',
name: 'Group 8',
type: 'PowerUsers' } },
{ user:
{ name: 'John',
user_id: '91f5e306-77f1-4aa1-b9d0-23136f57142d'} },
{ user:
{ name: 'John',
user_id: '91f5e306-77f1-4aa1-b9d0-23136f57142d'} },
{ user:
{ name: 'Jane',
user_id: '7f133d0d-47f3-479d-b6e7-5191bea52459'} },
{ user:
{ name: 'Jane',
user_id: '7f133d0d-47f3-479d-b6e7-5191bea52459'} },
{ group:
{ owner: 'A',
group_id: 'ef8c81f7-7066-49b2-9a03-bad731676a8c',
name: 'Group B',
type: 'PowerUsers' } },
{ user:
{ name: 'Max',
user_id: 'acf6abb8-08b3-4fc6-a4cb-f34ff523d628' } },
...
Because I have the same users in different groups, I can't use dedup(), and if the results where the same in NodeJS as Groovy, that'd be perfect. Unfortunately, they are not, and I don't understand why the results in NodeJS are all messed up, considering that the query is exactly the same
I feel like you could just use a nested project() to keep your group with your users:
g.V().hasLabel('group')
.has('type', 'PowerUsers')
.project('group', 'users')
.by(__.valueMap().by(__.unfold()))
.by(__.in().project('user').by(__.valueMap().by(__.unfold()).fold()))
In this way the you don't have to worry about ordering anything. I think it might be more Gremlin-esque though to use the "group" as a key in a Map with the values being a list of users:
g.V().hasLabel('group')
.has('type', 'PowerUsers')
.group()
.by(__.valueMap().by(__.unfold()))
.by(__.in().project('user').by(__.valueMap().by(__.unfold()).fold()))

Mongoose group documents by value but only return latest document each

I have a collection called "Words", where I save different Words in different languages. Words are stored in "content" and their language code in "lang" (en, de, fr).
This is my Words schema:
content: {
type: String
},
lang: {
type: String,
enum: ['en', 'de', 'fr']
}
I am now trying to retrieve the latest stored value for each language, only returning one document each.
This is my desired example output:
[{
lang: "en",
content: "Whats up"
},{
lang: "de",
content: "Guten Tag"
},{
lang: "fr",
content: "Salut"
}]
I've already tried to use aggregate function with group. But now the two letter language code gets returned as the document id:
Words.aggregate([{
$group: {
_id: '$lang'
}
}]
Words.aggregate([{$sort: {'_id': -1}},
{$group: {_id:'$lang',
word: {
$push: {
_id: '$_id',
content: '$content'
}
}
}},
{$project: {
_id:0,
lang:'$_id',
content: {$arrayElemAt:['$word.content',0]}
}}])
First, I used sort on _id by descending order. (Assuming you had use mongoDB auto-generated _id)
Next, group all the content by language and lastly project the first content which is the latest according to _id.

Suitescript 2.0 Display an array within an array with sublists

I'm creating a custom UI with a Suitelet, and I'm using the serverWidget module. I'm trying to represent an array of data, that can contain sub-arrays within them. I can't really find a great way to do that with the Suitescript APIs, as sublists only allow single fields within them. Does anyone have any ideas?
customers = [
{
name: '',
number:
contacts: [{
contactType:
contactName:
}]
},
{
name: '',
number:
contacts: [{
contactType:
contactName:
}]
},
{
name: '',
number:
contacts: [{
contactType:
contactName:
}]
}
]
Render the data in an inline html field, then you can display or anyway you like.

How to include documents as subdocuments in MongoDB?

I have a basic user collection that consists of document like so:
{
user: 3949fj9fn9rjhfne93,
name: "Jerry",
country: 'au',
friends: ['20fn39r4hf93', 'g9en3irhr934', '4i5henifuw92']
}
Each of those friends also has a document the same, along with there being a large collection of countries that can be queried via the country code.
{
code: 'AU',
name: 'Australia'
}, {
code: 'NZ',
name: 'New Zealand'
}
My question is, how would I include the full document for each of those array items within the result, like so:
{
user: 3949fj9fn9rjhfne93,
name: "Jerry",
country: {
code: 'AU',
name: 'Australia'
},
friends: [{
user: 20fn39r4hf93,
name: "Bob",
friends: ['2049429fr', 'djwij393i4']
}, {
user: g9en3irhr934,
name: "Foo",
friends: []
}, {
user: 4i5henifuw92,
name: "Bar",
friends: ['2049429fr']
}]
}
I am using Mongoose in my application, and I understand that this could be done by using a simple for loop and pushing the results to the user object and then returning it in node with res.json(user), although what if the user had hundreds (or even thousands) of friends? The request would be huge. I also need to do this in multiple places within my API.
Is there a more efficient way to achieve this?

Resources