C#でMongoDBでのサーバーサイドJavaScriptを実行する

 コレクションの集計処理をしたかったのだが、MapReduceでは望みの形に集計結果をまとめられなかった。だからサーバーサイドJavaScriptでやることにした。ただしサーバーサイドJavaScriptはセキュリティの懸念やパフォーマンスの注意点があるので気軽に使うものではない。今回はそれらが問題として出てこないので使うことにした。

 まずC#コード。サーバーサイドで実行するJavaScriptも埋め込んだ。
//using MongoDB.Driver;

//using MongoDB.Bson;
//using MongoDB.Driver.Core.Operations;
//using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
//using MongoDB.Driver.Core.Bindings;
//using System.Threading;

class Program
{
private static IMongoClient client;
private static IMongoDatabase DbConnection;

static void Main(string[] args)
{
client = new MongoClient("mongodb://127.0.0.1");
DbConnection = client.GetDatabase("helicon");

AggregateTag();
}

public static void AggregateTag()
{
var databaseName = new DatabaseNamespace("helicon");

var code = (BsonJavaScript)@"
function () {
// do something
}";

var messageEncodingSettings = new MessageEncoderSettings();
var operation = new EvalOperation(databaseName, code, messageEncodingSettings);
var source = new CancellationTokenSource();
var token = source.Token;
var writeBinding = new WritableServerBinding(client.Cluster);
operation.Execute(writeBinding, CancellationToken.None);
}
}


 あとはサーバサイドでJavaScriptを実行するために、接続ユーザに実行権限を持たせる。
Allow user to execute eval() command on MongoDB 3.x

データベースに管理権限者でログイン。そしてadminデータベースへ。
use admin;


ロールを作成。
db.createRole( { role: "executeFunctions", privileges: [ { resource: { anyResource: true }, actions: [ "anyAction" ] } ], roles: [] } )


ロールを接続ユーザに付加。
db.grantRolesToUser("someone", [ { role: "executeFunctions", db: "admin" } ])


付加されたことを確認。
db.getUser("someone") 


これで権限が付いたので、C#コードを実行すればMongoDBのサーバサイドJSが実行される。

 このブログのサイドバーの、タグや投稿月毎の記事のカウントにこの、MongoDBのサーバサイドJSを使っている。
comment: 0

JavaScriptで辞書型のキーをintだと思うな

 ぼくのJSのOSSライブラリにバグが報告されたので調べていたら、タイトルのような結論が出た。「辞書型」を「連想配列」に置き換えたい人は置き換えてもらっても構わないけど、本当はなにより「オブジェクト」と書きたい。というわけで以下オブジェクトと書く。

 JSのオブジェクトのキーは、intでキーを入れても、そのキーはstringに変換される。つまり…

オブジェクトのキーに整数1があるか調べたい。
Object.keys({1:"a"}).indexOf(1);

↑ "-1"

Object.keys({1:"a"}).indexOf("1");

↑ "0"

 でも下のようなのはキャストが効くのかありだったりするみたい。
1 in {1:"a"}


 上記はブラウザではもちろんNode.jsでも。
 JSのオブジェクトのキーが整数型を使えると思っていたらいかん。千行ぐらいのライブラリを書いているのにまったく知らんかった。
comment: 0

JavaScriptで文字列フォーマット

 アドベントカレンダーやってみたけどネタを生み出す時間が平日はなかなかきつい。今日も短めに。

 進化のスピードが早いJavaScript。文字列表現に変数を埋め込む方法が以前までなかったのだが、ぼくが気づかぬうちに追加されていた。

 文字列をバックティック「`」で囲む。バックティックであってシングルクォートではない。バックティックであってBUCK-TICKではない。
バックティックで囲んだら他言語と同じように、文字列中で変数名を「${}」で囲う。

var s = "foo";

console.log(`${s} bar`);
comment: 0

ドラッグ可能なイメージを使ってtextareaにイメージタグをドラッグアンドドロップで書き込む

 ブログに画像を入れるとき、その画像のURLを調べてタグを手書きで入れている。わりとめんどうだ。なのでドラッグアンドドロップを利用して、アップロードされてる画像一覧からイメージをタグで入れられるものを作った。

JSFiddleでのデモ

<textarea name="Body" cols="60" rows="20" ondrop="drop(event, this)" ondragover="allowDrop(event)"></textarea>

<div id="images"></div>
<script>
function allowDrop(ev) {
ev.preventDefault();
}

function drag(ev) {
ev.dataTransfer.setData('text/html', ev.target.src);
}

function drop(ev, target) {
ev.preventDefault();
console.log(target.id, ev.target.id)

var data = ev.dataTransfer.getData("text/html");
//alert(data);
var imgTag = "<img class='img' src='" + data + "' />";
var p = target.selectionStart;
var text = target.value;
target.value = text.substr(0, p) + imgTag + text.substr(p);
}
</script>
comment: 0

404ページにこだわる

 近年はWebページを訪れた人の興味をひきつけるため、404ページにもこだわることにおもむきがあるとされている。自分の趣味の悪さをいかして、こだわりの404ページを作ってみた。いろいろ整って来たらこのブログにのっける。

404ページ

comment: 0