前置き
以前、EvernoteAPIの話を書いていて、「検索のAPIは2つあるようなのですがそのうち調べます」とか言っていたものを書きました。EvernoteAPIのうち、ノートの検索に使うfindNotesとfindNotesMetadataの話です。ノートの検索に使うAPIであるfindNotesはdeperecatedとのことなので、推奨されているfindNotesMetadataを使ってみました。
概要
findNotesとfindNotesMetadataはどちらもノートのメタデータを返します。メタデータなので実際のノートの中身や、中身に埋め込まれた画像などのバイナリデータは含まれません。
findNotesMetadataで変わった点は、新しい引数を使ってこのメタデータに含めるデータを指定できるところです。findNotesで返されるメタデータに含まれるデータは固定なのですが、findNotesMetadataを使うことでより柔軟に結果を得られるようになったようです。(たぶん、速くなったりメモリを食わなくなったりしてるんだと思います。)また、容量の大きそうなノートの中身やバイナリデータのサイズなども取得できるので、その辺りを見つつうまいことやる、なんてこともできそうです。
この記事では、findNotesとfindNotesMetadataの使い方を示して、それぞれの違いについて説明します。
公式ドキュメント
説明します、といいつつ、この文章は解説というより、自分の使いみちにあった感じで書いたらこうなった、というところです。もっと色々調べたい方は公式のドキュメントをあたってください。というか、検索に限らず、API使って何かしたいと思ったら、まずドキュメントを片手に唸る感じです…。
この記事に関連するドキュメントはこちら。他は必要に応じてリンクを貼っています。またGUIDなど用語に関しては前に書いた記事や用語集 - Evernote Developersをご覧ください。
findNotesのコード例
さて、まずは今までの、findNotesを使ったコード例を乗せます。このfind_notesメソッドは、Evernoteのノートの属性のうちいくつかをまとめたNoteオブジェクトの配列を返します。
def find_notes(options={})
guid = options[:guid] # 検索するノートブックのGUID
words = options[:words] # 検索語句
count = options[:count] || 1 # 検索するノートの数
# 検索フィルタの作成
filter = Evernote::EDAM::NoteStore::NoteFilter.new
filter.notebookGuid ||= guid
filter.words ||= words
noteslist = @note_store.findNotes(@token, filter, 0, count)
noteslist.notes
end
findNotesMetadataのコード例
これをfindNotesMetadataを使って、同じように動作させようと修正をしたらこうなりました。(動作は同じですが、実は返り値が変わっています。これについては後述します。)
def find_notes(options={})
guid = options[:guid] # 検索するノートブックのGUID
words = options[:words] # 検索語句
count = options[:count] || 1 # 検索するノートの数
# 検索フィルタの作成
filter = Evernote::EDAM::NoteStore::NoteFilter.new
filter.notebookGuid ||= guid
filter.words ||= words
# ここから変更点
spec = Evernote::EDAM::NoteStore::NotesMetadataResultSpec.new
metadatas = @note_store.findNotesMetadata(@token, filter, 0, count, spec)
metadatas.notes
end
次にこの2つの違いについて説明します。
違いその1:spec
まず両者で変わったところ(返り値は後述します)というと、メソッドに渡す引数にspecが追加されました。
specにはEvernote::EDAM::NoteStore::NotesMetadataResultSpecというクラスのオブジェクトを渡します。このオブジェクトには、返り値のメタデータに何を含めるかを指定します。ただnewしただけのspecを使うと、GUIDしか含まれないメタデータを返してきます。そこで、タイトルも返して! というときには、つぎのように指定したspecをfindNotesMetadataメソッドに渡してやるといいようです。
spec.includeTitle = true
タイトルの他に、作成・更新・削除日時、ノートの中身のサイズなども検索結果のメタデータに含められるようです。(実際に何が含められるかは上記のspecのドキュメントをご覧ください。)
違いその2:返り値
次に違う点は返り値です。それぞれ次のようなオブジェクトを返します。
- findNotes
- findNotesMetadata
また上記のコード例では、どちらでもそれぞれのAPIの返り値に対して#notesメソッドを叩いています。この#notesメソッドの返り値が、検索に引っかかったノートのデータです。これの返り値も、findNotesとfindNotesMetadataで違います。
- findNotes#notes
- Evernote::EDAM::NoteStore::Noteの配列(ただしノートの中身と画像などのバイナリデータを省いたもの)
- findNotesMetadata#notes
このNoteMetadataに、specで指定したデータが入っています。
なお、空のspecを指定しても、ノートのGUIDは必ず含まれます。(というより、それがないとノートを指定できない)findNotes側で出てくるNoteオブジェクトもノートのGUIDを持っています。
まとめると次のようになります。
API | 返り値のクラス | #notesの返り値 | #notes で取得できるもの |
---|---|---|---|
findNotes | ÏNoteList | Noteの配列 | GUIDやタイトルなど(ノートのデータのうち、中身やバイナリデータを除いたもの |
findNotesMetadata | NotesMetadataList | NoteMetadataの配列 | GUIDとspecで指定したデータ |
じゃあ実際のノートの中身はどうすんだ、という話になりますが、そのときはGUIDを使ってノートの実体なり中身なりを取得します。この話はまた別に書きたいなあと思ってます。
まとめ
ノートを検索するときにはfindNotesMetadataの方が欲しいデータだけ拾ってこれるので便利そうです。findNotesではタイトルなど返り値に含まれるデータは固定ですが、findNotesMetadataでGUIDしかいらない、というときにも対応できます。私が作っているものについては、GUIDだけ必要なのでまさにこのパターンでした。
findNotesMetadataの方が、(場合によりますが)余計なデータを取ってこないのでその分早かったりメモリを食わなかったりしそうです。多分。おそらく検索結果が膨大になる場合には結構影響が出そうだなあと思っています。