MongoDB query with multiple search terms(regexes) in c# with 10gens driver? - mongodb

If we have
Blog{
Name 'Blog1'
Tags ['testing','visual-studio','2010','c#']
}
Blog{
Name 'Blog2'
Tags ['parallel','microsoft','c#']
}
Via the console we can execute and find all blog posts that contains some of the provided tags:
db.BlogPost.find({ 'Tags' : { '$regex' : ['/^Test/', '/^microsoft/', '/^visual/', '/^studio/', '/^c#/'] } });
How can we write the same query in c# 10gens driver ?
Is there any alternative if it can not be written via the 10gens c# driver ?
Query.Match only support one regex. Can we provide him multiple regexes, or we should combine
Query.Or(Query.Match("Test"), Query.Match("Micro"), Query.Match("Visual"))
I've managed to solve it with
I've managed to do it with
{ "$or" : [{ "Tags" : /^programm/i }, { "Tags" : /^microsoft/i }, { "Tags" : /^visual/i }, { "Tags" : /^studio/i }, { "Tags" : /^assert/i }, { "Tags" : /^2010/i }, { "Tags" : /^c#/i }] }
But something tells me that this is an ugly hack that may result in performance issues. What do you think guys ?
The final answer to the problem can be found on:
Official mongodb forum

Yes, the MongoDB c# driver should automatically do the right thing with instances of System.Text.RegularExpressions.Regex.
So you should be able to build the exact same query, except that you would use instances of Regex for ^Test, ^microsoft, ^visual, etc instead of strings.

Related

Query on all descendants of node

Given a collection of MongoDb documents with a property "myContacts" like this:
{
"_id": 123,
"myContacts" : {
"contacts" : {
"10" : {
"_id" : NumberLong(10),
"name" : "c1",
"prop" : true
},
"20" : {
"_id" : NumberLong(20),
"name" : "c2"
},
}
}
}
I want to select all documents, where at least one contact lacks the "prop" field.
I figured out a general query:
db.getCollection('xyz').find({ 'myContacts.contacts.???.prop': { $exists: false } })
The problem is that IDs of the contacts are part of the path and I cannot know them ahead. I want sth like 'myContacts.contacts.$anyChild.prop', but cannot find sth similar in the mongo docs.
Does it mean there is no way to do it?
PS: I cannot change the document structure, a live app uses it. I've spent some time with Google and my bet it's not possible. I however would like an opinion from people who have experience with Mongo.
Thank you guys for helpful comments, this got me going! I could get the results I wanted with:
db.getCollection('xyz').aggregate([{$project: {_id:1, contacts:{$objectToArray: "$myContacts.contacts"}}}, {$match: {"contacts.v.prop" : null}}])

Meteor Text Search has no results?

My webapp consists of just a list of topics and a search field to filter them with.
I started by inserting an object into my MongoDB:
$meteor mongo
meteor:PRIMARY> db.topics.insert({title:"Hello World!"});
I wrote this in my .coffee file to verify that it showed up as expected:
topics = new Mongo.Collection "topics"
if Meteor.isClient
Template.body.helpers {
topics: -> topics.find {}
}
That worked fine. So I decided to move to having a fixed filter of "Hello". I replaced topics.find {} with:
topics.find {$text: {$search: "Hello"}}
This caused my list to appear empty. I also tried this:
topics.find {title: {$text: {$search: "Hello"}}}
But that also did not work. What am I missing here?
(Also, this is my first time using CoffeeScript. The generated JavaScript file looked right to me, but if you see any unnecessary punctuation or other bad habits in here, please point it out to me. As someone who tends to help Python programmers, I know how obnoxious it is for people new to the language to be littering it with unnecessary semicolons.)
Update
I have added in the following server code as directed by Blakes Seven in his answer:
if Meteor.isServer
Meteor.startup -> topics._ensureIndex {title: "text"}
If I query the MongoDB from the command line as below, it works fine:
$meteor mongo
meteor:PRIMARY> db.topics.find({$text: {$search: "Hello"}})
{ "_id" : ObjectId("559495cf7b8f68a693d8a3a8"), "title" : "Hello World!" }
However, within my application, in the client code, topics.find {$text: {$search: "Hello"}} is still not working.
Update 2
Blakes Seven wanted to see this:
$meteor mongo
meteor:PRIMARY> db.topics.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "meteor.topics"
},
{
"v" : 1,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "title_text",
"ns" : "meteor.topics",
"safe" : true,
"weights" : {
"title" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
}
]
You need to create a "text index" on your collection before you can perform $text search queries.
You can create this index to deploy in Meteor.startup under server/indexes as:
Meteor.startup(function() {
topics._ensureIndex({ "title": "text" })
]);
MongoDB 3.x series recommends it's method .createIndex(), but the current meteor methods are like still calling .ensureIndex() at present.
This isn't really that much of a concern as the preferred method has expanded sytax to support additional features mostly, and none of these should be a general concern.
If you find a need for those features, you can always script "index" deployment outside of your Meteor application code.
Just as a sidenote, it's a general convention to refer to a collection model both in the "singular" rather than "plural" form, as the collection itself is the "plural" and not the model. Also a general convention is a "capital" first.

MongoDB - Count and group on key

I'm quite new to MongoDb and I'm trying to get my head around the grouping/counting functions. I want to retrieve a list of votes per track ID, ordered by their votes. Can you help me make sense of this?
List schema:
{
"title" : "Bit of everything",
"tracks" : [
ObjectId("5310af6518668c271d52aa8d"),
ObjectId("53122ffdc974dd3c48c4b74e"),
ObjectId("53123045c974dd3c48c4b74f"),
ObjectId("5312309cc974dd3c48c4b750")
],
"votes" : [
{
"track_id" : "5310af6518668c271d52aa8d",
"user_id" : "5312551c92d49d6119481c88"
},
{
"track_id" : "53122ffdc974dd3c48c4b74e",
"user_id" : "5310f488000e4aa02abcec8e"
},
{
"track_id" : "53123045c974dd3c48c4b74f",
"user_id" : "5312551c92d49d6119481c88"
}
]
}
I'm looking to generate the following result (ideally ordered by the number of votes, also ideally including those with no entries in the votes array, using tracks as a reference.):
[
{
track_id: 5310af6518668c271d52aa8d,
track_votes: 1
},
{
track_id: 5312309cc974dd3c48c4b750,
track_votes: 0
}
...
]
In MySQL, I would execute the following
SELECT COUNT(*) AS track_votes, track_id FROM list_votes GROUP BY track_id ORDER BY track_votes DESC
I've been looking into the documentation for the various aggregation/reduce functions, but I just can't seem to get anything working for my particular case.
Can anyone help me get started with this query? Once I know how these are structured I'll be able to apply that knowledge elsewhere!
I'm using mongodb version 2.0.4 on Ubuntu 12, so I don't think I have access to the aggregation functions provided in later releases. Would be willing to upgrade, if that's the general consensus.
Many thanks in advance!
I recommend you to upgrade your MongoDB version to 2.2 and use the Aggregation Framework as follows:
db.collection.aggregate(
{ $unwind:"$votes"},
{ $group : { _id : "$votes.track_id", number : { $sum : 1 } } }
)
MongoDB 2.2 introduced a new aggregation framework, modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated result.
The output will look like this:
{
"result":[
{
"_id" : "5310af6518668c271d52aa8d", <- ObjectId
"number" : 2
},
...
],
"ok" : 1
}
If this is not possible to upgrade, I recommend doing it in a programmatically way.

Mongodb setting a value in an array without .$

I have the query
choices.update({"subchoices.id":'fh3284'},
{$set : { "subchoices.$.name" : "le_new_choice"}}
);
the document:
{ subchoices : [ { "id" : "fh3284", name : "choice1" },
{ "id" : "fh3286", name : "choice2" }
], ... }
Is it possible to rewrite this without using the .$. operator for the (on its own not the one in the $set,$query, etc)? Im using meteor and the client side implementation which doesn't take the .$. yet.
It seems that impossible to do such update withou .$.
I've spent a lot of time to try to sovle it, but couldn't.

Retrieving only the relevant part of a stored document

I'm a newbie with MongoDB, and am trying to store user activity performed on a site. My data is currently structured as:
{ "_id" : ObjectId("4decfb0fc7c6ff7ff77d615e"),
"activity" : [
{
"action" : "added",
"item_name" : "iPhone",
"item_id" : 6140,
},
{
"action" : "added",
"item_name" : "iPad",
"item_id" : 7220,
}
],
"name" : "Smith,
"user_id" : 2
}
If I want to retrieve, for example, all the activity concerning item_id 7220, I would use a query like:
db.find( { "activity.item_id" : 7220 } );
However, this seems to return the entire document, including the record for item 6140.
Can anyone suggest how this might be done correctly? I'm not sure if it's a problem with my query, or with the structure of the data itself.
Many thanks.
You have to wait the following dev: https://jira.mongodb.org/browse/SERVER-828
You can use $slice only if you know insertion order and position of your element.
Standard queries on MongoDb always return all document.
(question also available here: MongoDB query to return only embedded document)