Mongoid学习

1. 安装mongoid

在Rails 配置文件Gemfile中,做如下配置


  gem 'mongoid', '~> 5.0.0'

2. 配置文件

执行 rails g mongoid:config 即可生成
myapp/config/mongoid.yml

在该配置文件中,你可以定制自己的配置


development:
 clients:
   default:
     database: mongoid
     hosts:
       - localhost:27017

还需要在 application.rb 文件中做如下配置,设置关系映射使用mongoid


  config.generators do |g|
    g.orm :mongoid
  end

3. Document

Document可以作为集合存储,也可以镶嵌到其他的Document中

Documents can be stored in their own collections in the database
or can be embedded in other Documents n levels deep.

4. 存储


  class Person
    include Mongoid::Document
  end

你可以在类级别更改该Person的存储位置


  class Person
    include Mongoid::Document
    store_in collection: "citizens", database: "other", client: "secondary"
  end

5. Fields

通过网络传输的String 参数,
Mongoid 提供了一个简单的机制来将他们转换成正确合适的类型,
通过定field定义


  class Person
    include Mongoid::Document
    field :first_name, type: String
    field :middle_name, type: String
    field :last_name, type: String
  end

除了String, 还有如下类型:


  Array
  BigDecimal
  Boolean
  Date
  DateTime
  Float
  Hash
  Integer
  BSON::ObjectId
  BSON::Binary
  Range
  Regexp
  String
  Symbol
  Time
  TimeWithZone

6. 访问设置Field

如果field已经定义,Mongoid提供了多种方式来访问field


  # Get the value of the first_name field
  person.first_name
  person[:first_name]
  person.read_attribute(:first_name)


  # Set the value for the first_name field
  person.first_name = "Jean"
  person[:first_name] = "Jean"
  person.write_attribute(:first_name, "Jean")

通过以下途径访问设置多值


  # Get the field values as a hash.
  person.attributes

  # Set the field values in the document.
  Person.new(first_name: "Jean-Baptiste", middle_name: "Emmanuel")
  person.attributes = { first_name: "Jean-Baptiste", middle_name: "Emmanuel" }
  person.write_attributes(
    first_name: "Jean-Baptiste",
    middle_name: "Emmanuel"
  )


存储设置Hash Field


class Person
  include Mongoid::Document
  field :first_name
  field :url, type: Hash

  # will update the fields properly and save the values
  def set_vals
    self.first_name = 'Daniel'
    self.url = {'home_page' => 'http://www.homepage.com'}
    save
  end

end

存储到数据库具体形式如下:


  { "_id" : ObjectId("56877d3408d67e50cb000008"),  "first_name" : "zhangsan", "url" : { "home_page" : "http://www.homepage.com" }, "updated_at" : ISODate("2016-01-02T07:33:34.721Z"), "created_at" : ISODate("2016-01-02T07:33:34.721Z") }

7. 设置默认值


  class Person
    include Mongoid::Document
    field :blood_alcohol_level, type: Float, default: 0.40
    field :last_drink, type: Time, default: ->{ 10.minutes.ago }
  end

或者根据Object的状态来设置默认值


  field :intoxicated_at, type: Time, default: ->{ new_record? ? 2.hours.ago : Time.now }

8. Custom Ids

如果你不想使用BSON::ObjectID ids, 你可以覆盖 Mongoid`s _id
值,只要你喜欢乐意。


  class Band
    include Mongoid::Document
    field :name, type: String
    field :_id, type: String, default: ->{ name }
  end

9. Dynamic Fields

默认情况Mongoid 不支持 dynamic fields,
你可以告诉mongoid支持dynamic fields 通过配置


 including Mongoid::Attributes::Dynamic in model


  class Person
    include Mongoid::Document
    include Mongoid::Attributes::Dynamic
  end

关于dynamic fields 有两个重要的规则

  1. 如果attribute 在document中存在,Mongoid 提供标准的getter 和 setter

  # Set the person's gender to male.
  person[:gender] = "Male"
  person.gender = "Male"

  # Get the person's gender.
  person.gender

  1. 如果attribute 在document中不存在,Mongoid不提供 getter 和
    setter,并且会强制抛出异常。在这种情况下,你可以使用
    [] 或 []= 或 read_attribute 或 write_attribute 方法

  >> bb = Teacher.new
  => #<Teacher _id: 5688bdb908d67e29cd000004, >
  >> bb[:gender]
  => nil
  >> bb.read_attribute(:gender)
  => nil
  >> bb[:gender] = "Male"
  => "Male"
  >> bb.write_attribute(:gender, "Female")
  => "Female"
  >> bb[:gender]
  => "Female"
  >> bb.gender
  => "Female"
  >> bb.name
  NoMethodError: undefined method `name' for #<Teacher _id: 5688bdb908d67e29cd000004, gender: "Female">

10. 查看attribute changes变化


  class Person
    include Mongoid::Document
    field :name, type: String
  end

  person = Person.first
  person.name = "Alan Garner"

  # Check to see if the document has changed.
  person.changed? #=> true

  # Get an array of the names of the changed fields.
  person.changed #=> [ :name ]

  # Get a hash of the old and changed values for each field.
  person.changes #=> { "name" => [ "Alan Parsons", "Alan Garner" ] }

  # Check if a specific field has changed.
  person.name_changed? #=> true

  # Get the changes for a specific field.
  person.name_change #=> [ "Alan Parsons", "Alan Garner" ]

  # Get the previous value for a field.
  person.name_was #=> "Alan Parsons"

11. 重置changes


  person = Person.first
  person.name = "Alan Garner"

  # Reset the changed name back to the original
  person.reset_name!
  person.name #=> "Alan Parsons"

12. 关于changes 和 save的关系

如果changes没有任何变更,Mongoid 也不会变更数据库的内容 通过Model#save
方法


  >> bb = Student.find(BSON::ObjectId("56877eae08d67e50cb00000b"))
  MONGODB | localhost:27017 | funds_development.find | STARTED | {"find"=>"students", "filter"=>{"_id"=>BSON::ObjectId('56877eae08d67e50cb00000b')}}
  MONGODB | localhost:27017 | funds_development.find | SUCCEEDED | 0.010262s
  => #<Student _id: 56877eae08d67e50cb00000b, created_at: 2016-01-02 07:39:26 UTC, updated_at: 2016-01-02 07:43:52 UTC, name: "jean", url: {"home_page"=>"www.jd.com"}, last_drink: 2016-01-02 07:29:26 UTC, intoxicated_at: 2016-01-02 05:39:26 UTC>
  >> bb.attributes
  => {"_id"=>BSON::ObjectId('56877eae08d67e50cb00000b'), "name"=>"jean", "url"=>{"home_page"=>"www.jd.com"}, "last_drink"=>2016-01-02 07:29:26 UTC, "intoxicated_at"=>2016-01-02 05:39:26 UTC, "updated_at"=>2016-01-02 07:43:52 UTC, "created_at"=>2016-01-02 07:39:26 UTC}
  >> bb.updated_at
  => Sat, 02 Jan 2016 07:43:52 UTC +00:00
  >> bb.updated_at.to_s(:db)
  => "2016-01-02 07:43:52"
  >> bb.save
  => true
  >> Student.find(BSON::ObjectId("56877eae08d67e50cb00000b")).updated_at.to_s(:db)
  MONGODB | localhost:27017 | funds_development.find | STARTED | {"find"=>"students", "filter"=>{"_id"=>BSON::ObjectId('56877eae08d67e50cb00000b')}}
  MONGODB | localhost:27017 | funds_development.find | SUCCEEDED | 0.0007s
  => "2016-01-02 07:43:52"

13. Readonly Attributes

你可以设置某些field为只读,创建之后便不能修改。


  class Band
    include Mongoid::Document
    field :name, type: String
    field :origin, type: String

    attr_readonly :name, :origin
  end

  band = Band.create(name: "Placebo")
  band.update_attributes(name: "Tool") # Filters out the name change.

如果你强制更新或修改某一个只读的field,便会抛出异常。


  band.update_attribute(:name, "Tool") # Raises the error.
  band.remove_attribute(:name) # Raises the error.

14. 继承

Document 继承来自与他们的fields, relations, validations 或者是
scopes 来自于他们的child documents.


  class Canvas
    include Mongoid::Document
    field :name, type: String
    embeds_many :shapes
  end

  class Browser < Canvas
    field :version, type: Integer
    scope :recent, where(:version.gt => 3)
  end

  class Firefox < Browser
  end

  class Shape
    include Mongoid::Document
    field :x, type: Integer
    field :y, type: Integer
    embedded_in :canvas
  end

  class Circle < Shape
    field :radius, type: Float
  end

  class Rectangle < Shape
    field :width, type: Float
    field :height, type: Float
  end

**Querying Subclasses**

  # Returns Canvas documents and subclasses
  Canvas.where(name: "Paper")
  # Returns only Firefox documents
  Firefox.where(name: "Window 1")

**Associations**

```

  firefox = Firefox.new
  # Builds a Shape object
  firefox.shapes.build({ x: 0, y: 0 })
  # Builds a Circle object
  firefox.shapes.build({ x: 0, y: 0 }, Circle)
  # Creates a Rectangle object
  firefox.shapes.create({ x: 0, y: 0 }, Rectangle)

  rect = Rectangle.new(width: 100, height: 200)
  firefox.shapes

```

15. 时间戳

Mongoid::Timestamps 提供了 created_at 和 updated_at field.


  class Person
    include Mongoid::Document
    include Mongoid::Timestamps
  end

或者你可以使用特殊的时间戳,creation 或 modification


  class Person
    include Mongoid::Document
    include Mongoid::Timestamps::Created
  end

  class Post
    include Mongoid::Document
    include Mongoid::Timestamps::Updated
  end

16. Persistence

Mongoid supports all expected CRUD operations for those familiar with
other Ruby mappers like Active Record or Data Mapper. What
distinguished Mongoid from other mappers for MongoDB is that the
general persistence operations perform atomic updated on only the
fields that have changed instead of writing the entire document to
the database each time.


Person.create(
first_name: "Heinrich",
last_name: "Heine"
)

Person.create([
{ first_name: "Heinrich", last_name: "Heine" },
{ first_name: "Willy", last_name: "Brandt" }
])

person.save
person.save(validate: false)

person.update_attributes!(
first_name: "Jean",
last_name: "Zorg"
)

person.update_attribute(:first_name, "Jean")


特殊的field用法

Model#upsert

如果这个attribute 存在,则覆盖,如果没有则插入。


  person = Person.new(
    first_name: "Heinrich",
    last_name: "Heine"
  )
  person.upsert

Model#touch

更新updated_at 时间戳,也可以根据配置级联更改关联关系。
该方法跳过validation 和 callbacks


  person.touch
  person.touch(:audited_at)

Model#delete

删除数据,并且没有任何回调

Model#destory

删除数据,并且执行回调

17. Atomic

当执行这些原子操作时,没有回调,没有校验


  person.add_to_set(aliases: "Bond")   # $addToSet
  person.bit(age: { and: 10, or: 12 }) # $bit
  person.inc(age: 1)                   # $inc
  person.pop(aliases: 1)               # $pop
  person.pull(aliases: "Bond")         # $pull

18. 查询

查询 DSL


  Band.where(name: "Depeche Mode")
  Band.
    where(:founded.gte => "1980-1-1").
    in(name: [ "Tool", "Deftones" ]).
    union.
    in(name: [ "Melvins" ])

Additional Query Methods

操作 例子
操作 例子
---- ----
Criteria#count
count 查询会涉及到数据库查询
Band.count
Band.where(name: "Photek").count
Criteria#distinct
获取单一field
Band.distinct(:name)
Band.where(:fans.gt => 100000).distinct(:name)
Criteria#each
迭代获取匹配数据
Band.where(members: 1).each do
Criteria#exists?
判断获取数据是否存在
Band.exists?
Band.where(name: "Photek").exists?
Criteria#find
获取一个文档或多个文档通过ids,如果没有找到就会报错
Band.find("4baa56f1230048567300485c")
Band.find( "4baa56f1230048567300485c", "4baa56f1230048567300485d")
Criteria#find_by
根据某一个field 来获取文档
Band.find_by(name: "Photek")
Criteria#find_or_create_by
根据attributes来查找文档,如果没有找到,就创建该文档
Band.where(:likes.gt => 10).find_or_create_by(name: "Photek")
Criteria#find_or_initialize_by
查找文档,若没找到,则初始化
Band.where(:likes.gt => 10).find_or_initialize_by(name: "Photek")
Criteria#first_or_create
根据attributes 查找第一个文档,如果不存在,就创建
Band.where(name: "Photek").first_or_create
Criteria#first_or_initialize
根据attributes 查找第一个文档,如果不存在,就初始化
Band.where(name: "Photek").first_or_initialize
Criteria#pluck
获取不为nil的值
Band.all.pluck(:name)

19. Eager Loading

Eager loaded is supported on all relations with the exception of polymorphic belongs_to associations.


  class Band
    include Mongoid::Document
    has_many :albums
  end

  class Album
    include Mongoid::Document
    belongs_to :band
  end

  Band.includes(:albums).each do |band|
    p band.albums.first.name # Does not hit the database again.
  end

20. 关联关系


>> p = Person.find('5687839408d67e50cb00000f')
MONGODB | localhost:27017 | funds_development.find | STARTED | {"find"=>"people", "filter"=>{"_id"=>BSON::ObjectId('5687839408d67e50cb00000f')}}
MONGODB | localhost:27017 | funds_development.find | SUCCEEDED | 0.005945s
=> #<Person _id: 5687839408d67e50cb00000f, first_name: "zhang", middle_name: "san", last_name: "bb">
>> p.addresses
=> [#<Address _id: 568783ce08d67e50cb000010, name: "one", addressable_type: nil, addressable_id: nil>, #<Address _id: 568783ce08d67e50cb000011, name: "two", addressable_type: nil, addressable_id: nil>]
>> p.addresses.target
=> [#<Address _id: 568783ce08d67e50cb000010, name: "one", addressable_type: nil, addressable_id: nil>, #<Address _id: 568783ce08d67e50cb000011, name: "two", addressable_type: nil, addressable_id: nil>]
>> p.addresses.base
=> #<Person _id: 5687839408d67e50cb00000f, first_name: "zhang", middle_name: "san", last_name: "bb">
>> p.addresses.metadata
=> #<Mongoid::Relations::Metadata
autobuild:    false
class_name:   Address
cyclic:       nil
counter_cache:false
dependent:    nil
inverse_of:   nil
key:          addresses
macro:        embeds_many
name:         addresses
order:        nil
polymorphic:  false
relation:     Mongoid::Relations::Embedded::Many
setter:       addresses=>

21. embeds_many 扩展


class Person
  include Mongoid::Document

  field :first_name, type: String
  field :middle_name, type: String
  field :last_name, type: String

  embeds_many :addresses do
    def find_by_name(name)
      where(name: name).first
    end

    def the_one
      @target.select{ |address| address.name == 'one' }
    end
  end
  has_many :posts, autosave: true
end

p.addresses.the_one # return [ address]
p.addresses.find_by_name('aaa') # return address


>> p = Person.find('5687839408d67e50cb00000f')
MONGODB | localhost:27017 | funds_development.find | STARTED | {"find"=>"people", "filter"=>{"_id"=>BSON::ObjectId('5687839408d67e50cb00000f')}}
MONGODB | localhost:27017 | funds_development.find | SUCCEEDED | 0.000462s
=> #<Person _id: 5687839408d67e50cb00000f, first_name: "zhang", middle_name: "san", last_name: "bb">
>> p.addresses
=> [#<Address _id: 568783ce08d67e50cb000010, name: "one", addressable_type: nil, addressable_id: nil>, #<Address _id: 568783ce08d67e50cb000011, name: "two", addressable_type: nil, addressable_id: nil>]
>> p.addresses.the_one
=> [#<Address _id: 568783ce08d67e50cb000010, name: "one", addressable_type: nil, addressable_id: nil>]
>> p.addresses.find_by_name('two')
=> #<Address _id: 568783ce08d67e50cb000011, name: "two", addressable_type: nil, addressable_id: nil>

22. 定制关系的名字

你可以随意定义关联关系的名字,但是你需要填写必要的选项来让mongoid找到对应
的类。


 class Lush
  include Mongoid::Document
  embeds_one :whiskey, class_name: "Drink", inverse_of: :alcoholic
 end

 class Drink
   include Mongoid::Document
   embedded_in :alcoholic, class_name: "Lush", inverse_of: :whiskey
 end

23. 关联关系校验

默认情况下,如下的关联关系,会存在校验。
如果需要去掉关联关系校验,则可以在定义类的时候,就去除。


  embeds_many
  embeds_one
  has_many
  has_one
  has_and_belongs_to_many


  class Person
    include Mongoid::Document

    embeds_many :addresses, validate: false
    has_many :posts, validate: false
  end

24. embeds_many 与 has_many 的区别

addresses 属于 embeds_many
posts 属于 has_many


  class Person
    include Mongoid::Document

    field :first_name, type: String
    field :middle_name, type: String
    field :last_name, type: String

    embeds_many :addresses do
      def find_by_name(name)
        where(name: name).first
      end

      def the_one
        @target.select{ |address| address.name == 'one' }
      end
    end
    has_many :posts, autosave: true
  end

> db.posts.find()
{ "_id" : ObjectId("5687862c08d67e29cd000001"), "name" : "101", "person_id" : ObjectId("5687839408d67e50cb00000f") }

> db.people.find({ "_id": ObjectId("5687839408d67e50cb00000f") })
{ "_id" : ObjectId("5687839408d67e50cb00000f"), "first_name" : "zhang", "middle_name" : "san", "last_name" : "bb", "addresses" : [ { "_id" : ObjectId("568783ce08d67e50cb000010"), "name" : "one" }, { "_id" : ObjectId("568783ce08d67e50cb000011"), "name" : "two" } ] }

由此可见,embeds_many 是嵌入到其他的document中
而has_many 是额外存在于其他的collections 中

25. 多态

一个child document 可以属于多个parent document,在parent document
中添加 as 选项来告诉Mongoid, 并且在child document中设置 polymorphic
选项。在child选项中,根据这个额外添加的选项,就可以获取到父类型。

多态存在于 has_and_belongs_to_many 的关系中。


  class Band
    include Mongoid::Document
    embeds_many :photos, as: :photographic
    has_one :address, as: :addressable
  end

  class Photo
    include Mongoid::Document
    embedded_in :photographic, polymorphic: true
  end

26. 级联回调

如果你想在父类上调用embedded document 的级联,需要做如下设置


  class Band
    include Mongoid::Document
    embeds_many :albums, cascade_callbacks: true
    embeds_one :label, cascade_callbacks: true
  end

  band.save # Fires all save callbacks on the band, albums, and label.

27. 约束行为

如果关联关系的一方删除,可以设置关联的另一方的关系

:delete: 删除关系,不会调用什么回调
:destroy: 删除关系,但是会调用回调函数
:nullify: 使关联关系的另一方,孤立
:restrict: 如果child不为空,则抛出异常


  class Band
    include Mongoid::Document
    has_many :albums, dependent: :delete
    belongs_to :label, dependent: :nullify
  end

  class Album
    include Mongoid::Document
    belongs_to :band
  end

  class Label
    include Mongoid::Document
    has_many :bands, dependent: :restrict
  end

  label = Label.first
  label.bands.push(Band.first)
  label.delete # Raises an error since bands is not empty.

  Band.first.delete # Will delete all associated albums.


28. 自动保存

Mongoid 和 Active Record 的另一个不同就是,不会自动
保存级联关系,是为了性能考虑。

镶嵌的关联并不需要设置autosave,因为实际上他就是属于父Object
的一部分。其余的关联关系,都可以设置 autosave


  class Band
    include Mongoid::Document
    has_many :albums, autosave: true
  end

  band = Band.first
  band.albums.build(name: "101")
  band.save #=> Will save the album as well.

29. 级联关系中存在的实用方法

在所有关联关系中都存在 name? 和 has_name? 的方法来校验relation
是否是空的


  class Band
    include Mongoid::Document
    embeds_one :label
    embeds_many :albums
  end

  band.label?
  band.has_label?
  band.albums?
  band.has_albums?

30. Embeds One

一对一的关联关系中,使用embeds_one 和 embedded_in 来作为属性关联。


  class Band
    include Mongoid::Document
    embeds_one :label
  end

  class Label
    include Mongoid::Document
    field :name, type: String
    embedded_in :band
  end

最后存储的结果如下


  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
    "label" : {
      "_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
      "name" : "Mute",
    }
  }

31. Embeds Many

一对多的嵌入关联关系,使用 embeds_many 和 embedded_in


  class Band
    include Mongoid::Document
    embeds_many :albums
  end

  class Album
    include Mongoid::Document
    field :name, type: String
    embedded_in :band
  end

最后存储结果如下:


  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
    "albums" : [
      {
        "_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
        "name" : "Violator",
      }
    ]
  }


32. Has One

一对一的关联关系中,使用 has_one 和 belongs_to


  class Band
    include Mongoid::Document
    has_one :studio
  end

  class Studio
    include Mongoid::Document
    field :name, type: String
    belongs_to :band
  end

最后存储结果如下


  # The parent band document.
  { "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }

  # The child studio document.
  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
    "band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
  }

33. Has Many

一对多的关联关系中,使用has_many 和 belongs_to


  class Band
    include Mongoid::Document
    has_many :members
  end

  class Member
    include Mongoid::Document
    field :name, type: String
    belongs_to :band
  end

最终存储结果如下


  # The parent band document.
  { "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }

  # A child member document.
  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
    "band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
  }

34. 多对多的关联关系

has_and_belongs_to_many

第一种方式


  class Band
    include Mongoid::Document
    has_and_belongs_to_many :tags
  end

  class Tag
    include Mongoid::Document
    field :name, type: String
    has_and_belongs_to_many :bands
  end

第二种方式


  class Band
    include Mongoid::Document
    has_and_belongs_to_many :tags, inverse_of: nil
  end

  class Tag
    include Mongoid::Document
    field :name, type: String
  end

最终存储结果如下


  # The band document.
  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
    "tag_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
  }

  # The tag document.
  {
    "_id" : ObjectId("4d3ed089fb60ab534684b7f2"),
    "band_ids" : [ ObjectId("4d3ed089fb60ab534684b7e9") ]
  }

35. 回调函数

  • after_initialize
  • after_build
  • before_validation
  • after_validation
  • before_create
  • around_create
  • after_create
  • after_find
  • before_update
  • around_update
  • after_update
  • before_upsert
  • around_upsert
  • after_upsert
  • before_save
  • around_save
  • after_save
  • before_destroy
  • around_destroy
  • after_destroy

36. 索引

给普通的field添加索引


  class Person
    include Mongoid::Document
    field :ssn

    index({ ssn: 1 }, { unique: true, name: "ssn_index" })
  end

给 embedded document 添加索引


  class Person
    include Mongoid::Document
    embeds_many :addresses
    index "addresses.street" => 1
  end

给多个列添加索引


  class Person
    include Mongoid::Document
    field :first_name
    field :last_name

    index({ first_name: 1, last_name: 1 }, { unique: true })
  end

使用下面命令添加索引


  rake db:mongoid:create_indexes

亦提供了删除所有二级索引的命令


   rake db:mongoid:remove_indexes

ruby-mongoid-tutorial

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • 2017年9月18日 星期一 晴 张荣轩妈妈 亲子日记第15篇 每个周一的早晨,都是我一周中最焦虑的时候...
    爱意暖人心阅读 267评论 0 1
  • 张东辉,焦点初级第43期坚持原创分享第35天 天气放晴,亲情融融,姐姐、弟弟和我,三家人,一众十几人,抓住假期的尾...
    星悦传奇阅读 199评论 0 0
  • 人生之中低谷最多的应该就是20几岁的年纪吧,没钱没房没车没爱人甚至工作还是一塌糊涂。但最好的时光也是20几岁,有梦...
    芳点儿阅读 431评论 0 1
  • 忙碌劳累的三月已经过去,从四月开始,很多人都希望自己工作顺利,家庭幸福,好运常伴。没错哦,有这个三个生肖在三月霉运...
    时允舜阅读 150评论 0 0