We have a content model where we set content at a central level, but users have the ability to edit the content down to subsidiary level if they want to. If they don't want to change anything from what gets set from central they don't have to.
Let's assume a simple api endpoint that just takes in companyId. This is how it would respond:
GET /offers (central values)
[{
offerId: 1,
title: "Central offer title",
paragraph: "Lorem ipsum central",
price: 100
}, {...more offers}]
Company 123
/offers?companyId=123
[{
offerId: 1,
title: "Company offer title",
paragraph: "Lorem ipsum central", // Inherited from central
price: 125
}, {...more offers}]
Company 456 which is a subsidiary to 123
/offers?companyId=456
[{
offerId: 1,
title: "Company offer title", // Inherited from Company 1
paragraph: "Lorem ipsum subsidiary",
price: 125, // Inherited from Company 1
custom_field: "A completely custom field for subsidiary" // Field only available for subsidiary
}, {...more offers}]
In previous implementations we have done something in the lines of:
{
offerId: 1,
values: [
{
companyId: null,
title: "Central offer title",
paragraph: "Lorem ipsum central",
price: 100
},
{
companyId: 123,
title: "Company offer title",
price: 125
},
{
companyId: 456,
paragraph: "Lorem ipsum subsidiary",
custom_field: "A completely custom field for subsidiary"
}
]
}
And then in the application we have compiled this down so values are specific for subsidiary, but still inheriting data from central or parent company.
Now that we're about to write new applications that should once again allow this type of content inheritance, we're having doubts about this approach and wonder if there's another way to model this.
What other ways exist to model this type of behavior?
Are you using mongoose? If so - use Discriminators:
const event1 = new Event({ time: Date.now() });
const event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
const event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
More on that topic in this fine read: https://dev.to/helenasometimes/getting-started-with-mongoose-discriminators-in-expressjs--22m9
If not - then I think you should follow the same approach as in mongoose - have each company as a separate document. Because in your old setup, there are a few things:
Company resides in Offer document
If multiple offers use the same companies, you'd duplicate company data, right?
There's no easy way to search for company - you get offers.values and search for a property inside. That's basically traversing your entire database.
If you only search by company (and not offer ID as you said), you can reverse them. But it's still weird. I'd split them in two separate things and use references between them. This way you could:
Find company by id
Find it's parent (do this until there is no parent; use aggregate to make it in a single query)
Get a list of offers for that company (document property) and query them
This approach would allow you to do the opposite (offer to company).
Related
I can able to search the case by company name
var mySearch = search.create({
type: search.Type.SUPPORT_CASE,
columns: [{
name: 'title'
}, {
name: 'company'
}],
filters: [{
name: 'company',
operator: 'is',
values: 'Test'
}]
});
return mySearch.run({
ld: mySearch.id
}).getRange({
start: 0,
end: 1000
});
But I am not able to search case by company id.
companyId is 115
Below are not working
i)
filters: [{
name: 'company',
operator: 'is',
values: 115
}]
ii)
filters: [{
name: 'companyid',
operator: 'is',
values: 115
}]
According to the Case schema company is a Text filter, meaning you would have to provide it with the precise Name of the company, not the internal ID.
Instead you may want to use the customer.internalid joined filter to provide the internal ID. Also, Internal ID fields are nearly always Select fields, meaning they do not accept the is operator, but instead require the anyof or noneof operator.
You can find the valid operators by field type on the Help page titled Search Operators
First, you can try this :
var supportcaseSearchObj = search.create({
type: "supportcase",
filters:
[
["company.internalid","anyof","100"]
],
columns:
[
search.createColumn({
name: "casenumber",
sort: search.Sort.ASC
}),
"title",
"company",
"contact",
"stage",
"status",
"profile",
"startdate",
"createddate",
"category",
"assigned",
"priority"
]
});
Second : how did I get this ? The answer is hint that will make your life easier :
Install the "NetSuite Saved Search Code Export" chrome plugin.
In Netsuite UI, create your saved search (it is always easier that doing it in code).
After saving the search, open it again for edition.
At the top right corner (near list, search menu in the netsuite page), you will see a link "Export as script" : click on it and you will get your code ;)
If you can not install the chrome plugin :
In Netsuite UI, create your saved search (it is always easier that doing it in code).
In your code, load your saved search
Add a log.debug to show the [loadedesearchVar].filters
You can then copy what you will see in the log to use it as your search filters.
Good luck!
I have inserted following values in my events collection
db.events.insert(
[
{ _id: 1, name: "Amusement Ride", description: "Fun" },
{ _id: 2, name: "Walk in Mangroves", description: "Adventure" },
{ _id: 3, name: "Walking in Cypress", description: "Adventure" },
{ _id: 4, name: "Trek at Tikona", description: "Adventure" },
{ _id: 5, name: "Trekking at Tikona", description: "Adventure" }
]
)
I've also created a index in a following way:
db.events.createIndex( { name: "text" } )
Now when I execute the following query (Search - Walk):
db.events.find({
'$text': {
'$search': 'Walk'
},
})
I get these results:
{ _id: 2, name: "Walk in Mangroves", description: "Adventure" },
{ _id: 3, name: "Walking in Cypress", description: "Adventure" }
But when I search Trek:
db.events.find({
'$text': {
'$search': 'Trek'
},
})
I get only one result:
{ _id: 4, name: "Trek at Tikona", description: "Adventure" }
So my question is why it dint resulted:
{ _id: 4, name: "Trek at Tikona", description: "Adventure" },
{ _id: 5, name: "Trekking at Tikona", description: "Adventure" }
When I searched walk it resulted the documents containing both walk and walking. But when I searched for Trek it only resulted the document including trek where it should have resulted both trek and trekking
MongoDB text search uses the Snowball stemming library to reduce words to an expected root form (or stem) based on common language rules. Algorithmic stemming provides a quick reduction, but languages have exceptions (such as irregular or contradicting verb conjugation patterns) that can affect accuracy. The Snowball introduction includes a good overview of some of the limitations of algorithmic stemming.
Your example of walking stems to walk and matches as expected.
However, your example of trekking stems to trekk so does not match your search keyword of trek.
You can confirm this by explaining your query and reviewing the parsedTextQuery information which shows the stemmed search terms used:
db.events.find({$text: {$search: 'Trekking'} }).explain().queryPlanner.winningPlan.parsedTextQuery
{
"terms" : [
"trekk"
],
"negatedTerms" : [ ],
"phrases" : [ ],
"negatedPhrases" : [ ]
}
You can also check expected Snowball stemming using the online Snowball Demo or by finding a Snowball library for your preferred programming language.
To work around exceptions that might commonly affect your use case, you could consider adding another field to your text index with keywords to influence the search results. For this example, you would add trek as a keyword so that the event described as trekking also matches in your search results.
There are other approaches for more accurate inflection which are generally referred to as lemmatization. Lemmatization algorithms are more complex and start heading into the domain of natural language processing. There are many open source (and commercial) toolkits that you may be able to leverage if you want to implement more advanced text search in your application, but these are outside the current scope of the MongoDB text search feature.
I'm trying to understand if it would actually be more efficient to read the entire document from Azure DocumentDb than it is to read a property that may have multiple objects in it?
Let's use this basketball team object as an example:
{
id: 123,
name: "Los Angeles Lakers",
coach: "Byron Scott",
players: [
{ id: 24, name: "Kobe Bryant" },
{ id: 3, name: "Anthony Brown" },
{ id: 4, name: "Ryan Kelly" },
]
}
If I want to get only a list of players, is it more efficient/faster for me to read the entire team document from which I can extract the players OR is it better to send SQL statement and try to read only the players from the document?
Returning only the players will be more efficient on the network, as you're returning less data. And, you should also be able to look at the Request Units burned for your query.
For example, I put your document into one of my collections and ran two queries in the portal (and if you do the same, and look at the bottom of the portal, you'll see the resulting Request Unit cost). I slightly modified your document with unique ID and quotes around everything, so I could load it via the portal:
{
"id": "basketball123",
"name": "Los Angeles Lakers",
"coach": "Byron Scott",
"players": [
{ "id": 24, "name": "Kobe Bryant" },
{ "id": 3, "name": "Anthony Brown" },
{ "id": 4, "name": "Ryan Kelly" }
]
}
I first selected just player data:
SELECT c.players FROM c where c.id="basketball123"
with an RU cost of 2.2:
I then asked for the entire document:
SELECT * FROM c where c.id="basketball123"
with an RU cost of 2.24:
Note: Your document size is very small, so there's really not much difference here. But at least you can see that returning a subset costs less than returning the entire document.
I have a node.js+mongoose rest api. I have two schemas which needs to be matched as and when a new entry is added to either one or on a timely basis. The matching will compare the whole set of documents with a set of paramters. Let's say, for example, i have the below 2 schemas -
Males: {
age: Number,
location: String,
language: String,
matchedFemales: []
}
Females: {
age: Number,
location: String,
language: String,
matchedMales: []
}
Now, i have to take a collection and scroll through all the documents and find matches. I have lots of parameters as matching criteria, but let us take for an example, language, location should be same and the age is almost equal (+ or - 1 year). Like below -
Males: [{
id: 1001,
age: 20,
location: London,
language: English,
matchedFemales: [2001,2002]
},
{
id: 1002,
age: 30,
location: London,
language: English,
matchedFemales: []
},
{
id: 1003,
age: 20,
location: Madrid,
language: Spanish,
matchedFemales: [2003]
}]
Females: [{
id: 2001,
age: 20,
location: London,
language: English,
matchedFemales: [1001]
},
{
id: 2002,
age: 19,
location: London,
language: English,
matchedFemales: [1001]
},
{
id: 2003,
age: 20,
location: Madrid,
language: Spanish,
matchedFemales: [1003]
}]
How to perform this matching and how to store the matches?
Should i iterate though each document in Male collection and find matches in the Female collection and update it? IF so, i plan to have a service do it and call this service every X minutes. This job will be time and resource consuming (as it has to go through each document and find matches) but will be run for a definite number of times per day. If its every 5 mins, then it will be run only 12 times in an hour.
Instead of matching all documents in LHS against all documents in RHS, as and when a record is getting inserted, i can find matches just for that document and update it. This method will be less time & resource consuming than the previous method, but it will be run more number of times i.e., for every insert/update this has to be done.
Or is there any other elegant way to do this?
P.S - If this question seems inappropriate, kindly direct me to the right source for reference or consultation.
I have a mongodb collection containing an array of objects, and I'd like to remove one or more of the array objects based on their properties.
Example document from my collection:
nickname: "Bob",
isLibrarian: false,
region: "South America",
favoriteBooks: [
{
title: "Treasure Island",
author: "Robert Louis Stevenson"
},
{
title: "The Great Gatsby",
author: "F. Scott Fitzgerald"
},
{
title: "Kidnapped",
author: "Robert Louis Stevenson"
}
]
In this example, how do I remove, from each of the documents in my collection, all objects within the favoriteBook array whose author matches "Robert Louis Stevenson"?
So that afterwards this user document would be
nickname: "Bob",
isLibrarian: false,
region: "South America",
favoriteBooks: [
{
title: "The Great Gatsby",
author: "F. Scott Fitzgerald"
}
]
and other documents in the collection would be equally trimmed of books by Stevenson.
Thank you in advance for any insight! I love MongoDB but I'm wondering if I've bitten off more than I can chew here...
The below line of mongodb will help you to delete the books that matches a particular author
db.collection.update(
{},
{$pull:{favoriteBooks:{author:"Robert Louis Stevenson"}}},
{multi:true}
);