Mongodb find with objectid in ballerina - database

In this case I have seen the official documentation of choreo, ballerina, but I could not find how to execute a query where I need to filter by the ObjectId, In Java I could do it by importing BSON, but I could not find the same in ballerina.
In the following example, it does not give an error, because that field is mapped to that type.
//map<json> queryString = {user_id: new object"61b75a0a08f2bf69b98a174c" };
map<json> queryString = {unique_id: 1 };
map<json> projectionDoc = {unique_id: true, destination_address: true, _id: true};
stream<Historial, error?> h_viajes = check mongoClient->find(collectionName = "trip_histories",projection = projectionDoc,filter = queryString);
check h_viajes.forEach(function(Historial datas){
io:println(datas.unique_id.toString());
io:println(datas._id.toString());
log:printInfo(datas.unique_id.toString());
});

Automatic casting of a string to The 12-byte ObjectId data type is not available in Ballerina, however it is possible to build it using the JSON notation provided by MongoDB.
For example:
map<json> filtersFields = {user_id: {"$oid": "60744b37d9bc8741f6edb714"}};
And through this syntax it is possible to filter by any field that is of type ObjectId

Ballerina changes json string to BSON object. For this purpose, the filterQuery has to be compatible with MongoDB Extended JSON. The correct filter for ObjectId type will be,
map<json> queryString = {_id: {"$oid": "<ObjectId>"}};
map<json> queryString = {_id: {"$oid": "63789aed271ba8943ff92574"}};
{"$oid": "<ObjectId>"} can be used for any field of type ObjectId.

Related

Firestore to query by an array's field value

I'm trying to run a simple query, where I search for a document that contains a value inside an object array.
For instance, look at my database structure:
I want to run a query similar to this:
db.collection('identites').where("partyMembers", "array-contains", {name: "John Travolta"})
What is the correct way to achieve this, is it even possible with Firestore?
Thanks.
As Frank has explained in his answer it is not possible, with array-contains, to query for a specific property of an object stored in an array.
However, there is a possible workaround: it is actually possible to query for the entire object, as follows, in your case:
db.collection('identites')
.where(
"partyMembers",
"array-contains",
{id: "7LNK....", name: "John Travolta"}
)
Maybe this approach will suit your needs (or maybe not....).
The array-contains operations checks if an array, contains a specific (complete) value. It can't check if an array of objects, contains an item with a specific value for a property.
The only way to do your query, is to add an additional field to your document with just the value you want to query existence on. So for example: partyMemberNames: ["John Travolta", "Olivia Newton"].
If you want to extract name: "John Travolta" from "partyMembers" array in a document. you can achieve this by some similar approach in which you can loop through all arrays in a document to find this name.
const [names, setNames] = React.useState([])
const readAllNames = async() => {
const snapshot = await firebase.firestore().collection('identites').doc(documentID).get()
const filterData = snapshot.data().question.map(val => val.name === "John Travolta" ? val : null)
setNames( filterData.filter(e=>e) );
}
This technique is used in perticular Document as we are giving .doc(documentID) This way you can get all the arrays having name: "John Travolta" in names constant.

React Native JSON Array as Parameter to LINQ Contains

I want to get a list of people that have the same tags as the user.
For that I need to use a react native fetch and the entity framework.
I also tried some raw sql with EF, but couldn't make it work, just don't know how.
I have two fetches. Both return a typical JSON object array. So I'm doing this:
var users = db.Users
.Include("TagUsers")
.Where(u => u.TagUsuario.Any(t => tags.Contains(t.idTag))).ToList();
The tags variable is an object array from a React Native Fetch, which in my C# function is of the type IList<>long.
The problem is that if this array have one element, like this const tags = [1]; or from the fetch like this
{0}
Tags:
idTag: 1
Name: "MyTag"
I can return the people with this tag, but if I do like this const tags = [1, 2]; or
{0}
Tags:
idTag: 1
Name: "MyTag"
{1}
Tags:
idTag: 2
Name: "AnotherTag"
It returns nothing on my LINQ request.
But if I do something like this on my C# function:
IList<>long tags = new List<>long();
tags.Add(1);
tags.Add(2);
It works perfectly.
The problem here is that the object array from the fetch is not "compatible" with the LINQ statement (Any, Contains). So I am in search of an alternative.
What do I have to do?
Change the IList parameter? I'm using that because accepts null without crashing.
Change the LINQ?
Use Raw SQL?
Maybe some conversion to get only an int array with the tags, not an object one.
Thanks for any tips and solutions.
Can you try to get the idTags from tags and use it as below.
var idTags = tags.Select(t => t.idTag);
var users = db.Users
.Include("TagUsers")
.Where(u => u.TagUsuario.Any(t => idTags.Contains(t.idTag))).ToList();

How can I perform a find in Mongo (meteor) that finds a document where an array matches? [duplicate]

This question already has answers here:
MongoDB Find Exact Array Match but order doesn't matter
(7 answers)
Closed 7 years ago.
I'm trying to return a Cursor in Meteor (using MongoDB).
I'm looking to find documents (MessageThreads collection) where a field of participants exactly matches an array I pass in.
Below is a sample MessageThread document
{
"_id": "YYSELCguhLurTeyNY",
"creator": "RLmnidY6GypdqDXZu",
"participants": [
"SNhRq4vQpwFBjnTSH",
"RLmnidY6GypdqDXZu"
],
}
When I perform an addMessage method, I'm trying to check first if a thread exists where participants exactly matches the array I pass in. This array will be formulated from the new message form tofield.
So, the documents should only be returned if all my array of participants are inside the documents participants field but no other. Eg: If a third person existed in the document who wasn't part of the new message to field then that document should not be returned.
Currently this is my query, which is obviously too simplistic.
existingThread = MessageThreads.findOne(participants: participants)
Any pointers? Thank you
EDIT: I'm having an issue using the provided duplicate answer (but not yet allowed to comment on that other thread)
For some reason existingThread is still finding a document if the array is different but the size is true.
EDIT 2:
Below is the code for my entire method in the event that it can help decipher where I am going wrong. In coffeescript (please excuse the tabbing, can't get it working in SO, sorry).
Meteor.methods
newMessage: (recipientIds, messageContent) ->
if !Meteor.userId()
return false
userId = Meteor.userId()
check recipientIds, [String]
check messageContent, String
participants = recipientIds
participants.push(userId)
participantCount = _.size(participants)
existingThread = MessageThreads.findOne participants:
$size: participantCount
$in: participants
if existingThread?
console.log "Thread exists: #{existingThread._id}"
MessageThreads.update existingThread,
$addToSet: messages: {sender: userId, content: messageContent}
$set: lastUpdated: new Date()
else
newThreadId = MessageThreads.insert
creator: userId
participants: participants
messages: [
{
sender: userId
content: messageContent
createdAt: new Date()
}
]
lastUpdated: new Date()
return newThreadId
You need the $all operator in your query which selects the documents where the value of a field is an array that contains all the specified elements. As you want to return a cursor, find() method is more appropriate since it returns a cursor. It does not immediately access the database or return documents. To access the documents in the cursor, cursors provide fetch() to return all matching documents, map() and forEach() to iterate over all matching documents, observe() and observeChanges() to register callbacks when the set of matching documents changes.
For your case, an example implementation would look something like this:
var existingThreadsCursor = MessageThreads.find({ "participants": { "$all": participants} });
var count = 0;
existingThreadsCursor.forEach(function (thread){
console.log("Thread with participants: " + JSON.stringify(thread.participants));
count++;
});

How to publish a mongodb array length as an additional collection field?

I have a mongodb collection with the following fields:
_id
name (string)
[items] (array of string)
secret (boolean)
I want to publish the all the _id, name fields and the item array length only (excluding the secret field) where the secret field is true.
I have read somewhere that I can add additional document properties in my find query, but my google foo does not work.
Here is what my publish method looks like without the additional items_count property:
Meteor.publish("all_items", function() {
return myItems.find(
{secret: true},
{fields:
{_id:1,name:1}
});
});
How can I create an additional field from the [item] length in my publication?
EDIT: it seems that I need to use an aggregate function and the $projectoperator. And it is not supported by meteor.
Can anyone confirm this to me (i.e. it is the only option and it is not supported)?
You can add aggregation framework support to Meteor, and then use a simple aggregation pipeline with $project stage as you mentioned, like to following:
myItems.aggregate(
[
{$match: {secret: true}},
{$project: {_id: 1, name: 1, items_count: {$size: '$items'}}}
]
)

Passing array name as parameters in mongoose

I'm using mongoose and I'm doing an update of my db by using findByIdAndUpdate() function. I'd like to push elements into different arrays present in my document. I have in my document different array with different names. May I pass as parameter the name array to this function or I should create different function where every function has a different nameArray?
this.findByIdAndUpdate(User._id,
{$push:{nameArray: 'element'}},
{upsert: true},
callback);
In Node.js 4.x you can use the computed property syntax to do this directly in the $push object literal:
this.findByIdAndUpdate(User._id,
{$push: {[nameArray]: 'element'}},
{upsert: true},
callback);
In previous versions, you need to build your $push object programmatically:
var push = {};
push[nameArray] = 'element';
this.findByIdAndUpdate(User._id,
{$push: push},
{upsert: true},
callback);

Resources