Let's say I have the following data:
{
ids: ['12345'],
images: [{
id: '12345',
}]
}
I know that I can write a schema that can enforce that ids exist, is an array, and has a string value. I can also enforce that images have an id that is a string. But is there a way that I can enforce that the following two data blocks will fail validation using a JSON schema?
{
ids: [], // should fail because the id '12345' doesn't exist, and the images array is a different length than the ids array
images: [{
id: '12345',
}]
}
Or:
{
ids: ['54321'],// should fail because 12345 doesn't match any of the ids
images: [{
id: '12345',
}]
}
Related
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}]})
Inside my companies table there is a company collection I have an array of users.
I need to change one of the users name ('David' to 'Solomon').
I don't mind changing to insert a new user object instead David.
But I don't mind to keep the same id and just change the name field from 'David' to 'Solomon'
company: {
id: cde9e41d-8d16-4054-907f-cc92a69d68e0
name: 'Gold Crowns Ltd',
users: [
{
id: abc9e41d-8d16-4054-907f-cc92a69d68e0
name: 'David' // <-------- I want to change 'David' to 'Solomon'
},
{
id: fgh9e41d-8d16-4054-907f-cc92a69d68e0
name: 'Saul'
},
],
}
Which option will work best and what should be the query in DynamoDB
I have a user.expenses collection like this
{
userId: ObjectId("62f332b93753ac926ff6ac62"),
expenses: [
{
name: 'electricity',
assigned: 400,
given: 400,
},
{
name: 'restaurant',
assigned: 2100,
given: 0,
}
]
}
I will get userId and expenses.name(electricity) from the request. I need to check if the user.expenses collection has any expenses document whose name is electricity and assigned is not equal to given.
I used $elemMatch and could check if there are any embedded documents whose name is electricity.
db.user.expenses.find({
userId: ObjectId('62f332b93753ac926ff6ac62'),
expenses: {
$elemMatch: {
name: 'electricity',
},
},
});
EDIT
I also tried to use $where. But it only can be applied to the top-level document.
Query
you cant do it with query operators because you want to reference a field but you can do it with aggregate operators and $filter
filter the array and keep only if electricity and assigned!=given
keep the document if at least one sub-document was electricity with assigned!=given
Playmongo
aggregate(
[{"$match":
{"$expr":
{"$ne":
[{"$filter":
{"input": "$expenses",
"cond":
{"$and":
[{"$eq": ["$$this.name", "electricity"]},
{"$ne": ["$$this.assigned", "$$this.given"]}]}}}, []]}}}])
I would like to use different schemas for an array of objects based on a value.
items: [{
name: "a"
...
},
{
name: "b"
...
}]
How can I validate the item with name: "a" with another schema than item with name: "b" based on the value of name?
I am having a bit of trouble here. So I want to show a user's profile. The user belongs to groups. The logged in user can see details of any groups they have in common. Here is some example data
{
_id: "1234",
battletag: "Fake#1234",
guilds: [{
name: "Lok'Narosh!",
rank: 4,
roles: ['casual']
}, {
name: "Warlords of Draenor",
rank: 2,
roles: ['PvP', 'raider']
}, {
name: "Lok'Tar Ogar!",
rank: 3,
roles: ['raider']
}],
}
I can get the current user's groups and reduce it to ['Lok'Narosh!', 'Warlords of Draenor'], meaning that Lok'tar Ogar should be omitted from the results.
The main problem I am coming across is that most operations I know only return the first result. For example, with $elemMatch:
The $elemMatch operator limits the contents of an field from the query results to contain only the first element matching the $elemMatch condition.
Is there a way that I can filter this list to contain all matching elements against a list of elements?
You can use aggregate:
$unwind operator to deconstruct 'guilds' field.
Apply criteria with $match
Reconstruct array.
db.getCollection('yourColl').aggregate({$unwind:"$guilds"},{$match:{"guilds.rank":{$gte:2.0}}},{$group:{ "_id":"$_id", "battletag":{$first:"$battletag"},"guilds":{$addToSet:"$guilds"}}})