MongoDB c# query subdocument - mongodb

I have a mongodb document, such as
"_id" : ObjectId("565e6c9b10bcd93ca8d1206c"),
"listHeader" : [
{
"strName" : "MSID",
"strVal" : "154800"
},
{
"strName" : "Operation",
"strVal" : "8221"
},
}
I want to query MSID =154800 and Operation =8221,
How to do in C#???
I had
var queryMod = Query.And(
Query<ModuleTestData>.EQ(e =>e.MSID , strSerialNumber),
Query<ModuleTestData>.EQ(e => "listHeader.Operation",
operation));
Not working? Any suggestions?

Use regular expressions matching as below. The 'i' shows case insensitivity.
var collections = mongoDatabase.GetCollection("Abcd");
var queryA = Query.And(
Query.Matches("strName", new BsonRegularExpression("MSID", "i")),
Query.Matches("strVal", new BsonRegularExpression("154800", "i")));
var queryB = Query.And(
Query.Matches("strName", new BsonRegularExpression("Operation","i")),
Query.Matches("strVal", new BsonRegularExpression("8221", "i")));
var getA = collections.Find(queryA);
var getB = collections.Find(queryB);

Related

Mongodb findOneAndUpdate is not working

I'm trying to update document in mongodb collection but it's not working for me. Here is the function all fields are come to the backend. I use mlab online mongo db
router.post(
'/accept',
(req,res) => {
const leaveFields = {};
leaveFields._id = req.body.id;
leaveFields.name = req.body.name;
leaveFields.reason = req.body.reason;
leaveFields.from = req.body.from;
leaveFields.to = req.body.to;
leaveFields.user_id = req.body.user_id;
leaveFields.leaveType = req.body.leaveType;
console.log(req.body.id);
Leave.find({user_id:req.body.user_id}) //{ "_id":ObjectId("req.body.id") }
.then(leave =>{
if(leave){
Leave.findOneAndUpdate(
{_id : req.body.id},
{$set : leaveFields},
{new : true}
)}else{
res.status(400).json(errors);
}
}
)
.catch(err=>res.status(404).json({ noleavefound: 'No leaves found' }));
Here you are setting _id to leavefields object and
const leaveFields = {};
leaveFields._id = req.body.id;
here you are passing _id field also to your update.
{$set : leaveFields}
_id field is an immutable filed. So, Exclude _id field and then check.

Selective specific columns in SailsJS via API

I want to select certain columns be returned back from sailsjs / waterline / API
Given the search parameters:
var searchParams = {
"select":["ClientTypeID"]
, "where": {
"or" :
[{"ClientType": {"contains": "MAINT"}}]
}};
I make API call :
/api/reference/client_type?select=ClientTypeID&where=%7B%22or%22:%5B%7B%22ClientType%22:%7B%22contains%22:%22MAINT%22%7D%7D%5D%7D
based on
Select specific fields from database
I believe I am making the correct query, however, the JSON object that is returned has the all the columns of entity vs the 1 I wish to request ClientTypeID?
This is known issue but I've found workaround. You can override default find blueprint with your own. You need to create api/blueprints/find.js file with content:
var _ = require('lodash');
var Promise = require('bluebird');
var actionUtil = require('sails/lib/hooks/blueprints/actionUtil');
var takeAliases = _.partial(_.pluck, _, 'alias');
var populateAliases = function (model, alias) {
return model.populate(alias);
};
module.exports = function (req, res) {
_.set(req.options, 'criteria.blacklist', ['limit', 'skip', 'sort', 'populate', 'fields']);
var fields = req.param('fields') ? req.param('fields').replace(/ /g, '').split(',') : [];
var populate = req.param('populate') ? req.param('populate').replace(/ /g, '').split(',') : [];
var Model = actionUtil.parseModel(req);
var where = actionUtil.parseCriteria(req);
var limit = actionUtil.parseLimit(req);
var skip = actionUtil.parseSkip(req);
var sort = actionUtil.parseSort(req);
var findQuery = _.reduce(_.intersection(populate, takeAliases(Model.associations)), populateAliases, Model.find().where(where).limit(limit).skip(skip).sort(sort));
var countQuery = Model.count(where);
Promise.all([findQuery, countQuery])
.spread(function (_records, _count) {
var records = fields.length > 0 ? _.map(_records, _.partial(_.pick, _, fields)) : _records;
return [records, null, null, {
criteria: where,
limit: limit,
start: skip,
end: skip + limit,
total: _count
}];
})
.spread(res.ok)
.catch(res.serverError);
};
This is general blueprint I'm using in all of my projects. For all fixed blueprints you can take a look here - https://github.com/ghaiklor/generator-sails-rest-api/tree/dev/generators/app/templates/api/blueprints

SAPUI5: How to filter data with 2 or more values

I'm currently trying some stuff with/in SAPUI5 and I've implemented a very simple search like this:
var filters = [];
var query = evt.getParameter("query");
if (query && query.length > 0) {
var nameFilter = new sap.ui.model.Filter("name", sap.ui.model.FilterOperator.Contains, query);
filters.push(nameFilter);
}
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(filters);
Now I have following issue: with this logic I can just search, or rather filter, by the name of a person. I've also some additional fields like age, gender, etc and I want to perform a search for the age or gender, too.
So I've tried to create a 2nd filter, like "genderFilter", which is using the "gender" field. After this adding this 2nd filter with the .push() method to the filters[]..but this isn't working.
I've already tried to watch the documentation, watched different examples, tried different ways - but I'm helpless. Can please someone help me with this issue?
For the requirement this code will work.
var list = this.getView().byId("list");
var binding = list.getBinding("items");
if( !query ) {
binding.filter( [] );
}
else {
binding.filter( [ new sap.ui.model.Filter([
new sap.ui.model.Filter("name", sap.ui.model.FilterOperator.Contains, query ),
new sap.ui.model.Filter("gender", sap.ui.model.FilterOperator.Contains, query )
],false)
]
According to the API
For manual filtering you should always pass the FilterType
If you change your code to
list.getBinding("items").filter(filters, sap.ui.model.FilterType.Application);
it should work.
See also https://openui5.hana.ondemand.com/docs/guide/BindingAggregations.html at the very bottom.
I achieved this with the below code:-
var oFilter = new sap.ui.model.Filter("name",sap.ui.model.FilterOperator.Contains,searchString);
var oFilter1 = new sap.ui.model.Filter("ID",sap.ui.model.FilterOperator.Contains,searchString);
var comFil = new sap.ui.model.Filter([oFilter,oFilter1]);
var oList = sap.ui.getCore().byId("dealerList");
oList.getBinding("items").filter(comFil,sap.ui.model.FilterType.Application);
to combine multiple filters you've to write the filter this way:
new sap.ui.model.Filter({
filters: [
new sap.ui.model.Filter(col1, , ,val),
new sap.ui.model.Filter(col2, , ,val)
],
and: false
})
Source: https://sapui5.hana.ondemand.com/docs/api/symbols/sap.ui.model.Filter.html#constructor
Then you can filter in multiple columns with OR.
Have only one filter in the filters array for each of the criteria and it should work,
var filters = [];
var sFilter;
var query = evt.getParameter("query");
if (query && query.length > 0) {
if(query == "name" )
{
sFilter = new sap.ui.model.Filter("name", sap.ui.model.FilterOperator.Contains, query);
}
else if(query == "gender")
{
sFilter = new sap.ui.model.Filter("gender", sap.ui.model.FilterOperator.Contains, query);
}
//and so on...
filters.push(sFilter);
}
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(filters);
I hope I got everything right:
Here is how filtering more than one column when binding data to a table:
oTable.bindRows({
path : "/modelData",
filters: [new sap.ui.model.Filter("severity", sap.ui.model.FilterOperator.EQ, '2'),
new sap.ui.model.Filter("severity", sap.ui.model.FilterOperator.EQ, '3')]
});
I had to use both. So at the end this worked for me.
var oFilters = new sap.ui.model.Filter({
filters: [
oFilter,
oFilter2
],
and: false
});
evt.getSource().getBinding("items").filter(oFilters, sap.ui.model.FilterType.Application);
Thanks for the help!
var afilters = [];
var query = evt.getParameter("query");
afilters.push(new sap.ui.model.Filter("name", sap.ui.model.FilterOperator.Contains, query);
afilters.push(new sap.ui.model.Filter("age", sap.ui.model.FilterOperator.Contains, query);
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(new sap.ui.model.Filter({filters: afilters, and: true|false}));
Simple way to bind two or more filters.
var sQuery = oEvent.getParameter("value");
var oBinding = oEvent.getSource().getBinding("items");
oBinding.filter([
new sap.ui.model.Filter("column A", sap.ui.model.FilterOperator.Contains, sQuery),
new sap.ui.model.Filter("column B", sap.ui.model.FilterOperator.Contains, sQuery)
]);

inserting a new document in the arrray of documents

I want to add a new document to the following document having an outer key "User"
{
name:himani,
User:[
{
_id:e25ffgf627627,
Name:User1
},
{
_id:fri2i2jhjh9098,
Name:User2
}
]
};
Below is my code in which I am trying to add a new document to already existing document.
My code is:
var server = MongoServer.Create("mongodb://username:password#localhost:27017/?safe=true");
SafeMode mode = new SafeMode(true);
SafeModeResult result = new SafeModeResult();
var db = server.GetDatabase("himani");
var coll = db.GetCollection("test");
BsonDocument document = new BsonDocument();
document.Add("name", "himani");
result = coll.Insert(document, mode);
BsonDocument nested = new BsonDocument();
nested.Add("1", "heena").Add("2", "divya");
BsonArray a = new BsonArray();
a.Add(2);
a.Add(5);
nested.Add("values", a);
document["3"] = new BsonArray().Add(BsonValue.Create(nested));
coll.Save(document);
var query = Query.And(
Query.EQ("name", "himani"),
Query.EQ("3.1", "heena")
);
var match = coll.FindOne(query);
var update = Update.AddToSet("3", new BsonDocument {{ "count", "2" }});
coll.Update(query, update);
I want to add a new document to the User array. I am doing this by above code but its not working.Please tell me the right way of doing it.
I don't understand your document structure at all... and the only "user" array I could find in here was a field called "3". Your code does in fact work and appends a document into the "3" array. The below is the result after running your code. Perhaps you could be more clear as to what you want your document to look like after you have "appended" a user.
{
"_id":ObjectId("4fa7d965ce48f3216c52c6c7"),
"name":"himani",
"3":[
{
"1":"heena",
"2":"divya",
"values":[ 2, 5 ]
},
{
"count":"2"
}
]
}

Lucene 'join' how-to? part II

Part I here...
Requirement:
search by multiple values in multiple fields AND Where Bar.Id == argBar.Id
var parser = new MultiFieldQueryParser
(new[] { "Name", "Title" }, new SimpleAnalyzer());
parser.???(string.Format("Bar.Id:{0}",argBar.Id)); // o_0
var query = Session.CreateFullTextQuery
(parser.Parse(searchValue), new[] { typeof(Foo) });
Found this:
Query searchQuery = MultiFieldQueryParser.Parse
(term, new[] {"title", "description"},
new[] {BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD},
new StandardAnalyzer());
So, theoretically - i should be able to add argBar.Id and BooleanClause.Occur.Must, but there isn't such an overload in Lucene.Net 2.4.0.2.
var bq = new BooleanQuery();
bq.Add(parser.Parse(searchValue), BooleanClause.Occur.SHOULD);
bq.Add(new TermQuery
(new Term("Bar.Id", argBar.Id.ToString()), BooleanClause.Occur.Must);
var r = Session.CreateFullTextQuery(bq, new[] {typeof(Foo)});
//victory