Ale*_*lex 11 nhibernate asp.net-mvc solr solrnet
我目前正处于一个相当大的基于问题/答案的应用程序中(有点像stackoverflow/answerbag.com)我们使用SQL(Azure)和nHibernate进行数据访问,使用MVC进行UI应用程序.
到目前为止,架构大致沿着stackoverflow db的方向,因为我们有一个Post表(包含两个问题/答案)
可能会使用以下存储库接口的内容:
public interface IPostRepository
{
void PutPost(Post post);
void PutPosts(IEnumerable<Post> posts);
void ChangePostStatus(string postID, PostStatus status);
void DeleteArtefact(string postId, string artefactKey);
void AddArtefact(string postId, string artefactKey);
void AddTag(string postId, string tagValue);
void RemoveTag(string postId, string tagValue);
void MarkPostAsAccepted(string id);
void UnmarkPostAsAccepted(string id);
IQueryable<Post> FindAll();
IQueryable<Post> FindPostsByStatus(PostStatus postStatus);
IQueryable<Post> FindPostsByPostType(PostType postType);
IQueryable<Post> FindPostsByStatusAndPostType(PostStatus postStatus, PostType postType);
IQueryable<Post> FindPostsByNumberOfReplies(int numberOfReplies);
IQueryable<Post> FindPostsByTag(string tag);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在哪里/如何使用solr来更好地查询这些"帖子"(我将使用solrnet与Solr进行实际通信)
理想情况下,我将SQL db用作持久存储 - 上述IQueryable操作的大部分将转移到某种SolrFinder类(或类似的东西)
Body属性是导致当前问题的属性 - 它相当大,并且减慢了对sql的查询.
我的主要问题是,例如,如果有人"更新"帖子 - 例如,添加新标签,则整个帖子将需要重新编制索引.显然,这样做需要这样的查询:
"SELECT*FROM POST WHERE ID = xyz"
这当然会很慢.Solrnet有一个nHibernate工具 - 但我相信这与上面的结果相同?
我想到了解决这个问题的方法,我希望你对此有所了解:
我的设计遇到了另一个问题: 从哪里调用"重新索引"方法?MVC控制器?或者我应该有一个"PostService"类型类,它包装了IPostRepository的实例?
任何指针都非常受欢迎!
Nic*_*cki 27
在我工作的电子商务网站上,我们使用Solr提供快速分面和搜索产品目录.(在非Solr geek术语中,这意味着"ATI Cards(34),NVIDIA(23),Intel(5)"风格的导航链接,您可以使用它来浏览Zappos,Amazon等网站上的产品目录. NewEgg和Lowe's.)
这是因为Solr的目的是快速和良好做这样的事情,并尝试做这种事情有效地在传统的关系型数据库,很好,不会发生,除非你想开始添加和删除索引飞得又满EAV,这只是咳嗽 Magento 咳嗽傻.因此,我们的SQL Server数据库是"权威"数据存储,Solr索引是该数据的只读"投影".
你到目前为止和我在一起是因为听起来你处于类似情况.下一步是确定Solr索引中的数据是否可能稍微陈旧是否正常.你可能已经接受了这样一个事实,即它会有些陈旧,但接下来的决定是
例如,我有所谓的"Worker",这是一个使用Quartz.NETIJob
定期执行C#实现的Windows服务.每3个小时,其中一个被执行的工作就是RefreshSolrIndexesJob
,而且所有工作都是ping HttpWebRequest
到http://solr.example.com/dataimport?command=full-import
.这是因为我们使用Solr的内置DataImportHandler来实际从SQL数据库中获取数据; 该工作只需定期"触摸"该URL以使同步工作.由于DataImportHandler会定期提交更改,因此这些更改都在后台有效运行,对Web站点的用户而言是透明的.
这意味着产品目录中的信息最长可达3小时.用户可以在目录页面上单击"Medium In Stock(3)"的链接(因为这种分面数据是通过查询SOLR生成的),但随后在产品详细信息页面上看到没有库存的介质(因为在此在页面中,数量信息是未经缓存和直接针对数据库查询的少数事物之一.这很烦人,但在我们的特殊情况下(我们是一个相当小的业务而不是那么高的流量)通常很少,并且当我们从头开始重建整个索引时它将在3小时内修复,所以我们接受了这个作为一个合理的权衡.
如果你能接受这种程度的"陈旧",那么这个后台工作者流程是一个很好的方法.您可以采取"每隔几小时重建整个事物"的方法,或者您的存储库可以将ID插入表中,比如说,dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr
然后后台进程可以定期扫描该表并在重建时仅更新Solr中的那些文档考虑到数据集的大小或复杂性,从头开始的整个索引定期是不合理的.
第三种方法是让你的仓库生成一个后台线程,在或多或少在同一时间问候到当前文档更新Solr的指标,因此数据只有几秒钟陈旧:
class MyRepository
{
void Save(Post post)
{
// the following method runs on the current thread
SaveThePostInTheSqlDatabaseSynchronously(post);
// the following method spawns a new thread, task,
// queueuserworkitem, whatevever floats our boat this week,
// and so returns immediately
UpdateTheDocumentInTheSolrIndexAsynchronously(post);
}
}
Run Code Online (Sandbox Code Playgroud)
但如果出于某种原因爆炸,你可能会错过Solr的更新,所以让Solr定期"彻底清除并刷新"仍然是一个好主意,或者有一个收割者背景工作者类型的服务,检查出 - Solr的每个人都曾在蓝色的月亮中找到过最新的数据.
至于从Solr查询这些数据,您可以采取一些方法.一个是隐藏Solr完全通过存储库的方法存在的事实.我个人不建议这样做,因为您的Solr架构可能会被无耻地定制为将访问该数据的UI; 我们已经对使用Solr的提供易于刻面,分类和信息快速显示的决定,所以我们不妨用它最大程度.这意味着当我们意味着访问Solr时以及当我们意味着访问最新的非缓存数据库对象时,使其在代码中显式化.
在我的情况下,我最终使用NHibernate进行CRUD访问(加载ItemGroup
,使用其定价规则,然后保存它),放弃存储库模式,因为当NHibernate及其映射时我通常不会看到它的值已经抽象了数据库.(这是个人选择.)
但在数据查询时,我知道得很好,如果我使用它的导向目录,目的(我关心速度和查询),或在后端管理应用程序表显示(我关心的货币).为了在网站上查询,我有一个名为的界面ICatalogSearchQuery
.它有一个Search()
接受的方法SearchRequest
,我定义了一些参数-选择方面,搜索项,页码,每页项目数,等等-并给回SearchResult
--remaining面,结果数量,在此结果页面等.非常无聊的东西.
有趣的是,它的实现ICatalogSearchQuery
是使用ICatalogSearchStrategy
下面的s 列表.默认策略是SolrCatalogSearchStrategy
,通过简单的老式直接命中SOLR HttpWebRequest
并解析XML HttpWebResponse
(这比一些SOLR客户端库更容易使用,恕我直言,虽然它们可能因为我上次查看时有所改善他们一年多前).如果该策略由于某种原因抛出异常或呕吐,则DatabaseCatalogSearchStrategy
直接命中SQL数据库 - 尽管它忽略了一些参数SearchRequest
,如分面或高级文本搜索,因为那样做效率低,这是我们首先使用Solr的全部原因.这个想法通常是SOLR通过全功能的荣耀快速回答我的搜索请求,但是如果某些东西爆炸并且SOLR发生故障,那么该站点的目录页面仍然可以通过点击数据库以"缩减功能模式"运行直接设置有限的功能.(由于我们在代码中明确指出这是一个搜索,因此该策略可以在忽略某些搜索参数方面采取一些自由,而不必担心过于严重地影响客户端.)
关键点:重要的是,对于可能过时的数据存储与权威数据存储执行查询的决定已经明确 -如果我想要快速,可能具有高级搜索功能的陈旧数据,我使用ICatalogSearchQuery
.如果我想要使用插入/更新/删除功能的缓慢,最新的数据,我使用NHibernate的命名查询(或您的情况下的存储库).如果我在SQL数据库中进行更改,我知道进程外的工作服务最终将更新Solr,使事情最终保持一致.(如果某些事情真的很重要,我可以直接播放一个事件或ping SOLR商店,告诉它更新,如果必须,可能在后台线程中.)
希望能给你一些见解.
小智 8
我们使用solr来查询大型产品数据库.约100万件产品,30家门店.
我们所做的是在产品表上使用触发器,在Sql服务器上使用stock表.
每次更改一行时,它会标记要重新编制索引的产品.我们有一个窗口服务,抓住这些产品,并每隔10秒发布到Solr.(每批限量100件产品).
它是股票的超高效,几乎实时的信息.
归档时间: |
|
查看次数: |
3221 次 |
最近记录: |